Home > Net >  The multi-part identifier "[column name]" could not be bound in UPDATE of TEMP Table
The multi-part identifier "[column name]" could not be bound in UPDATE of TEMP Table

Time:05-12

I am trying to create a stored procedure whereupon I input a (simple for now) query into a temp table, and then replace some of the data with data from a different table based on a key.

Here is the complete code:

CREATE PROCEDURE GetInquiryList
AS
BEGIN
SET NOCOUNT ON

IF OBJECT_ID('tempdb..#Inq ') IS NOT NULL
DROP TABLE #Inq

 SELECT i.*,q.QuoteID INTO #Inq FROM Inquiries i left join Quotes q on i.InquiryId = q.InquiryId 
    WHERE i.YNDeleted = 0

    --SELECT * FROM #Inq

UPDATE #Inq  
    SET j.InquiryCustomerName = c.CustomerName,
        j.InquiryCustomerEmail = c.CustomerEmail, 
        j.InquiryCustomerPhone = c.CustomerPhone1, 
        j.InquiryBestTimetoCall = c.CustomerBestTimetoCall, 
        j.InquiryDay = c.customerDay, 
        j.InquiryNight = c.CustomerNight 
  SELECT c.CustomerName,
    c.CustomerEmail,
    c.CustomerPhone1,
    c.CustomerBestTimetoCall, 
    c.customerDay, 
    c.CustomerNight
        FROM Customers c 
            INNER JOIN #Inq j ON 
                j.InquiryCustomerID =  c.CustomerID

SELECT * FROM #Inq

END

I get the following error:

Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound

I get this error for whatever column is placed first after the SET command.

Both query pieces of this work independently (the first select creating the temp table and the joined query at the bottom). The data returned is correct. I have tried using aliases (SELECT c.CustomerName AS Name, ...).

Originally, I used "#Inq i" in the second command, but changed to "j" out of an abundance of caution.

I have also run the command against the original table (substituting the Inquiry table for the temp table #Inq, and that fails as well).

Shortening it to this:

UPDATE #Inq  
    SET j.InquiryCustomerName = c.CustomerName,
        j.InquiryCustomerEmail = c.CustomerEmail, 
        j.InquiryCustomerPhone = c.CustomerPhone1, 
        j.InquiryBestTimetoCall = c.CustomerBestTimetoCall, 
        j.InquiryDay = c.customerDay, 
        j.InquiryNight = c.CustomerNight 
        FROM Customers c 
            INNER JOIN #Inq j ON 
                j.InquiryCustomerID =  c.CustomerID

I get a different error:

Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound

I'm sure it's probably something simple,(so simple that I can't find any references in any of my searches).

I'm sure it has something to do with the fact that you can't update the same instance of the table used in the join (I'm going to have to re-join again with a "k" alias). How do I do this?

data from the first query

data from the first query

data from the second select statement on the actual temp table

Here is what I updated the stored procedure to, which works exactly how I need it to:

SET NOCOUNT ON

IF OBJECT_ID('tempdb..#Inq ') IS NOT NULL
    DROP TABLE #Inq

 SELECT i.* INTO #Inq FROM (
select inquiries.InquiryId, 
        inquiries.InquiryDateReceived,
        inquiries.InquiryCustomerID,
        cust.CustomerName as InquiryCustomerName,
        cust.CustomerEmail as InquiryCustomerEmail,
        cust.CustomerPhone1 as InquiryCustomerPhone,
        cust.CustomerBestTimeToCall as InquiryBestTimeToCall,
        cust.CustomerDay as InquiryDay,
        cust.CustomerNight as InquiryNight,
        inquiries.InquiryServiceType,
        inquiries.InquiryServiceID,
        inquiries.InquiryTimeframe,
        inquiries.InquiryProjectDescription,
        inquiries.InquiryDateResponded,
        inquiries.InquiryCustomerReply,
        inquiries.YNMigrated,
        inquiries.InquiryDateClosed,
        inquiries.YNClosed,
        inquiries.YNDeleted
from inquiries inner join dbo.Customers as cust  
     on inquiries.InquiryCustomerID =  cust.CustomerID and inquiries.InquiryCustomerID > 0

UNION ALL
select inquiries.InquiryId,
        inquiries.InquiryDateReceived,
        inquiries.InquiryCustomerID,
        InquiryCustomerName,
        InquiryCustomerEmail,
        InquiryCustomerPhone,
        InquiryBestTimeToCall,
        InquiryDay,
        InquiryNight,
        inquiries.InquiryServiceType,
        inquiries.InquiryServiceID,
        inquiries.InquiryTimeframe,
        inquiries.InquiryProjectDescription,
        inquiries.InquiryDateResponded,
        inquiries.InquiryCustomerReply,
        inquiries.YNMigrated,
        inquiries.InquiryDateClosed,
        inquiries.YNClosed,
        inquiries.YNDeleted
from inquiries WHERE inquiries.InquiryCustomerID = 0
) i

    select i.*, q.QuoteID 
    FROM #Inq i left join dbo.Quotes as q 
      on i.InquiryId = q.InquiryId 
    WHERE i.YNDeleted = 0
    
END

CodePudding user response:

Just stop using this pattern without a really good reason. Here it only appears to create more work for the database engine with no obvious benefit. Your procedure - as posted - has trivially simple queries so why bother with the temp table and the update?

It is also time to start learning and using best practices. Terminate EVERY statement - eventually it will be required. Does order of the rows in your resultset matter? Usually it does and that is only guaranteed when that resultset is produced by a query that includes an ORDER BY clause.

As a developing/debugging short cut, you can harness the power of CTEs to help you build a working query. In this case, you can "stuff" your first query into a CTE and then simply join the CTE to Customers and "adjust" the columns you need in that resultset.

WITH inquiries as (
    select inq.*, qt.QuoteID 
    FROM dbo.Inquiries as inq left join dbo.Quotes as qt 
      on inq.InquiryId = qt.InquiryId 
    WHERE inq.YNDeleted = 0
)
select inquiries.<col>, 
       ...,  
       cust.CustomerName as "InquiryCustomerName", 
       ... 
from inquiries inner (? guessing) dbo.Customers as cust  
     on inquiries.InquiryCustomerID =  cust.CustomerID
order by ...
;

Schema names added as best practice. Listing the columns you actually need in your resultset is another best practice. Note I did not do that for the query in the CTE but you should. You can choose to create aliases for your resultset columns as needed. I listed one example that corresponds to your UPDATE attempt.

It is odd and very suspicious that all of the columns you intended to UPDATE exist in the Inquiries table. Are you certain you need to do that at all? Do they actually differ from the related columns in the Customer table? Also odd that the value 0 exists in InquiryCustomerID - suggesting you might have not a FK to enforce the relationship. Perhaps that means you need to outer join rather than inner join (as I wrote). If an outer join is needed, then you will need to use CASE expressions to "choose" which value (the CTE value or the Customer value) to use for those columns.

CodePudding user response:

After learning a lot more about how things get bound to models, and how to further use sql, here is what my stored procedure looks like:

ALTER PROCEDURE  [dbo].[GetInquiryList]
    @InquiryID int = 0
AS
BEGIN
SET NOCOUNT ON

    select i.InquiryId, 
        i.InquiryDateReceived,
        i.InquiryCustomerID,
        
        InquiryCustomerName = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryCustomerName
            ELSE c.CustomerName
        END,

        InquiryCustomerEmail = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryCustomerEmail
            ELSE c.CustomerEmail
        END,

        InquiryCustomerPhone = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryCustomerPhone
            ELSE c.CustomerPhone1
        END,

        InquiryBestTimetoCall = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryBestTimetoCall
            ELSE c.CustomerBestTimetoCall
        END,

        InquiryDay = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryDay
            ELSE c.CustomerDay
        END,

        InquiryNight = 
         CASE i.InquiryCustomerID 
            WHEN 0 THEN i.InquiryNight
            ELSE c.CustomerNight
        END,
        i.InquiryServiceType,
        i.InquiryServiceID,
        i.InquiryTimeframe,
        i.InquiryProjectDescription,
        i.InquiryDateResponded,
        i.InquiryCustomerReply,
        i.YNMigrated,
        i.InquiryDateClosed,
        i.YNClosed,
        i.YNDeleted, ISNULL(q.QuoteId,0) AS Quoteid
    FROM dbo.Inquiries i  
    LEFT JOIN  dbo.Quotes q ON i.InquiryId = q.InquiryId
    LEFT JOIN  dbo.Customers c ON i.InquiryCustomerID = c.CustomerId
    WHERE i.YNDeleted = 0
END 

I'm sure there are additional enhancements that could be made, but avoiding the union is a big savings. Thanks, everyone.

  • Related