SQL Server 在事实表上插入查询
Posted
技术标签:
【中文标题】SQL Server 在事实表上插入查询【英文标题】:SQL Server Insert Query on Fact Table 【发布时间】:2010-07-12 07:42:32 【问题描述】:好的,我的事实表有这个问题。当在我的事实表上有外键的数据库中的所有其他表上输入新数据时,我需要自动填充它。在我的存储过程中,我编译了我拥有的所有插入语句,最后,因为我还想更新我的事实表,所以我放置了这个查询:
INSERT INTO Fact (AccountID, ExpenseID, DateTimeID, InventoryID)
VALUES (@AccountID,
(SELECT ExpenseID FROM Expenses WHERE WaterBill = @WaterBill AND ElectricBill = @ElectricBill AND OfficeRent = @OfficeRent,
SELECT DateTimeID FROM DateTime WHERE MonthNo = @MonthNo AND Date = @Date AND Year = @Year AND Time = @Time AND Day = @Day AND DayNo = @DayNo,
SELECT InventoryID FROM Inventory WHERE ProductInID = @ProductInID AND ProductOutID = @ProductOutID)
但是,我收到以下消息的错误:
Subqueries are not allowed in this context. Only scalar expressions are allowed.
有人可以帮帮我吗?非常感谢。 :)
我的完整程序:
ALTER PROCEDURE [dbo].[ExpenseListInsert]
@AccountID char(6),
@ExpenseID int,
@DateTimeID int,
@InventoryID int,
@WaterBill decimal(19, 4),
@ElectricBill decimal(19, 4),
@OfficeRent decimal(19, 4),
@Miscellaneous decimal(19, 4),
@ProductsExpense decimal(19, 4),
@Subtotal decimal(19, 4),
@ProductInID int,
@ProductOutID int,
@Product30001 int,
@Product30002 int,
@Product30003 int,
@MonthNo int,
@Date int,
@Year int,
@Time char(11),
@Day char(10),
@DayNo int
AS
INSERT INTO Expenses (WaterBill, ElectricBill, OfficeRent, Miscellaneous, ProductsExpense, Subtotal)
VALUES(@WaterBill, @ElectricBill, @OfficeRent, @Miscellaneous, @ProductsExpense, @Subtotal)
INSERT INTO ProductIn (ProductInID, Product30001, Product30002, Product30003)
VALUES(@ProductInID, @Product30001, @Product30002, @Product30003)
INSERT INTO ProductOut (ProductOutID, Product30001, Product30002, Product30003)
VALUES(@ProductOutID, '0', '0', '0')
INSERT INTO Inventory (ProductInID, ProductOutID)
VALUES (@ProductInID, @ProductOutID)
INSERT INTO DateTime (MonthNo, Date, Year, Time, Day, DayNo)
VALUES (@MonthNo, @Date, @Year, @Time, @Day, @DayNo)
SELECT @ExpenseID = ExpenseID FROM Expenses WHERE WaterBill = @WaterBill AND ElectricBill = @ElectricBill AND OfficeRent = @OfficeRent
SELECT @DateTimeID = DateTimeID FROM DateTime WHERE MonthNo = @MonthNo AND Date = @Date AND Year = @Year AND Time = @Time AND Day = @Day AND DayNo = @DayNo
SELECT @InventoryID = InventoryID FROM Inventory WHERE ProductInID = @ProductInID AND ProductOutID = @ProductOutID
INSERT INTO Fact (AccountID, ExpenseID, DateTimeID, InventoryID)
VALUES (@AccountID, @ExpenseID, @DateTimeID, @InventoryID)
RETURN
【问题讨论】:
【参考方案1】:假设每个子查询只能返回一条记录,这应该可以工作
DECLARE @ExpenseID int, @DateTimeID int, @InventoryID int
SELECT @ExpenseID= ExpenseID FROM Expenses WHERE WaterBill = @WaterBill AND ElectricBill = @ElectricBill AND OfficeRent = @OfficeRent
SELECT @DateTimeID = DateTimeID FROM DateTime WHERE MonthNo = @MonthNo AND Date = @Date AND Year = @Year AND Time = @Time AND Day = @Day AND DayNo = @DayNo
SELECT @InventoryID = InventoryID FROM Inventory WHERE ProductInID = @ProductInID AND ProductOutID = @ProductOutID
INSERT INTO Fact (AccountID, ExpenseID, DateTimeID, InventoryID)
VALUES (@AccountID, @ExpenseID, @DateTimeID, @InventoryID)
【讨论】:
先生,谢谢。但我尝试运行这个存储过程。但是每次我运行我的应用程序时,它都会给我一个错误,说我的程序需要一个未提供的@ExpenseID 参数。我现在将编辑我的问题以放置我的存储过程。谢谢。【参考方案2】:您不能使用普通 INSERT 执行子查询,您需要执行 INSERT...SELECT:
INSERT INTO [Fact] (AccountID, ExpenseID, DateTimeID, InventoryID)
SELECT @AccountID,
(SELECT ExpenseID FROM [Expenses] WHERE WaterBill = @WaterBill AND ElectricBill = @ElectricBill AND OfficeRent = @OfficeRent),
(SELECT DateTimeID FROM [DateTime] WHERE MonthNo = @MonthNo AND [Date] = @Date AND [Year] = @Year AND [Time] = @Time AND [Day] = @Day AND DayNo = @DayNo),
(SELECT InventoryID FROM Inventory WHERE ProductInID = @ProductInID AND ProductOutID = @ProductOutID)
我还会查看可能的性能瓶颈的执行计划,并查看 Expense、DateTime 和 Inventory 表上的索引。
【讨论】:
我不明白这个查询的作用。你能给我解释一下吗?谢谢。 :) 当你使用 VALUES 和 INSERT 时,你需要传入 SCALAR 值。当您将 SELECT 与 INSERT 一起使用时,您可以传入一个表格结果集,在这种情况下,是您的三个子查询的结果。 这听起来可能很愚蠢,但我还是不明白。我真正想做的是: INSERT INTO Fact (A, B, C, D) VALUES (A, B 应该来自另一个表,C 应该来自另一个表,D 应该来自另一个表) 这是 SELECT INSERT 适用于这种情况吗?非常感谢。 嗯,这就是你正在做的,当你做 INSERT INTO [Fact] (A, B, C, D) SELECT将您的查询更改为:
INSERT INTO Fact (AccountID, ExpenseID, DateTimeID, InventoryID)
SELECT @AccountID,
(SELECT ExpenseID FROM Expenses WHERE WaterBill = @WaterBill AND ElectricBill = @ElectricBill AND OfficeRent = @OfficeRent),
(SELECT DateTimeID FROM DateTime WHERE MonthNo = @MonthNo AND Date = @Date AND Year = @Year AND Time = @Time AND Day = @Day AND DayNo = @DayNo),
(SELECT InventoryID FROM Inventory WHERE ProductInID = @ProductInID AND ProductOutID = @ProductOutID)
【讨论】:
这个查询给了我以下错误信息:Msg 102, Level 15, State 1, Procedure ExpenseListInsert, Line 38 ',' 附近的语法不正确。消息 102,级别 15,状态 1,过程 ExpenseListInsert,第 39 行 ',' 附近的语法不正确。 @Kim Rivera - 已修复。我以为你把每个SELECT
括起来了以上是关于SQL Server 在事实表上插入查询的主要内容,如果未能解决你的问题,请参考以下文章