我正在尝试创建一个存储过程,在此过程中,我将一个(目前简单的)查询输入到一个临时表中,然后使用基于键的不同表中的数据替换一些数据。
下面是完整的代码:
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
我得到以下错误:
Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound
对于在SET
命令之后放置的任何列,我都会得到此错误。
这两个查询部分独立工作(第一个选择创建临时表和底部的连接查询)。返回的数据正确。我已经尝试使用别名(SELECT c.CustomerName AS Name, ...
)。
最初,我使用"#Inq I "在第二个命令中,却改成了"出于谨慎。
我还对原始表运行了该命令(将查询表替换为临时表#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
FROM Customers c
INNER JOIN #Inq j ON
j.InquiryCustomerID = c.CustomerID
我得到一个不同的错误:
Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound
我相信它可能是简单的东西,(简单到我在任何搜索中都找不到任何参考)。
我确信这与您无法更新连接中使用的表的相同实例有关(我将不得不再次使用"k"重新连接)。别名)。我该怎么做呢?
第一个查询的数据
第一个查询的数据
来自实际临时表上第二个select语句的数据
下面是我更新的存储过程,它的工作方式正是我所需要的:
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
不要再使用这种模式了。在这里,它似乎只会为数据库引擎增加更多的工作,而没有明显的好处。您的过程-如所述-有非常简单的查询,所以为什么要麻烦临时表和更新?
也是时候开始学习和使用最佳实践了。终止每个语句-最终将需要它。结果集中的行顺序重要吗?通常情况下,只有当包含ORDER by子句的查询生成结果集时,才能保证这一点。
作为开发/调试的捷径,您可以利用cte的强大功能来帮助您构建工作查询。在这种情况下,你可以"stuff"您的第一个查询到CTE,然后简单地将CTE加入到客户和"调整";结果集中需要的列。
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 ...
;
模式名称作为最佳实践添加。列出结果集中实际需要的列是另一种最佳实践。请注意,我没有为CTE中的查询这样做,但您应该这样做。您可以根据需要选择为结果集列创建别名。我列出了一个与您的UPDATE尝试相对应的示例。
奇怪且非常可疑的是,您打算更新的所有列都存在于询问表中。你确定你有必要这么做吗?它们实际上与Customer表中的相关列不同吗?同样奇怪的是,在InquiryCustomerID中存在值0——这表明您可能没有FK来强制关系。也许这意味着您需要外部连接而不是内部连接(正如我所写的)。如果需要外部连接,则需要使用CASE表达式来"选择"。为这些列使用哪个值(CTE值或Customer值)。
在学习了如何将事物绑定到模型以及如何进一步使用sql之后,下面是我的存储过程的样子:
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
我确信还有其他的增强可以做,但是避免联合是一个很大的节省。谢谢,每一个人。