2010-04-06 105 views
1

我正在做一个SQL Insert来填充我的表。我在一个表中有一个唯一的生成的ID,我想在另一个表中使用我的连接。这可能吗?我可以在SQL存储过程中分配一个变量吗?

.NET MVC -

using (SqlConnection connect = new SqlConnection(connections)) 
{ 
    SqlCommand command = new SqlCommand("ContactInfo_Add", connect); 
    command.Parameters.Add(new SqlParameter("name", name)); 
    command.Parameters.Add(new SqlParameter("address", address)); 
    command.Parameters.Add(new SqlParameter("Product", name)); 
    command.Parameters.Add(new SqlParameter("Quantity", address)); 
    command.Parameters.Add(new SqlParameter("DueDate", city)); 
    connect.Open(); 
    command.ExecuteNonQuery(); 
} 

SQL SERVER -

ALTER PROCEDURE [dbo].[Contact_Add] 
@name varchar(40), 
@address varchar(60), 
@Product varchar(40), 
@Quantity varchar(5), 
@DueDate datetime 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT INTO DBO.PERSON 
    (Name, Address) VALUES (@name, @address) 
    INSERT INTO DBO.PRODUCT_DATA 
    (PersonID, Product, Quantity, DueDate) VALUES (@Product, @Quantity, @DueDate) 
END 

的代码插入罚款。我如何将自动生成的PersonID拉到PRODUCT_DATA中使用?

+0

user54197看看松下的答案,我就可以了评论。如果有人在不知不觉中更改了您的存储过程,则使用范围标识返回PersonID存在一些潜在问题。 – msarchet 2010-04-06 15:29:01

+0

@msarchet:仔细阐述这些潜在问题是什么?当然,如果有人可以在不知道它如何工作的情况下改变存储过程,那么可以破坏存储过程,但这与SCOPE_IDENTITY本身无关 - 它们可能会破坏“OUTPUT INSERTED”子句。 – LukeH 2010-04-06 16:04:04

+0

刚才你说的,这不是SCOPE_IDENTITY本身的问题,这很好。使用插入的输出更加确定,因为如果有人改变存储过程的顺序它不会中断。这并不完美,因为无论你如何返回价值,显然有人可能会破坏你的SP。使用像'@variable int output'这样的参数是获取输出最明显的方法。但是仍然有人可以打破这一点,但这仍然很难。 – msarchet 2010-04-06 16:08:44

回答

3

您可以使用SCOPE_IDENTITY得到最后插入的标识值:

DECLARE @PersonID INT 

INSERT INTO dbo.Person (Name, Address) 
VALUES (@Name, @Address) 

SET @PersonID = SCOPE_IDENTITY() 

INSERT INTO dbo.Product_Data (PersonID, Product, Quantity, DueDate) 
VALUES (@PersonID, @Product, @Quantity, @DueDate) 
+0

你可以在不使用SCOPE_IDENTITY()的情况下插入到两个表中,并且在一个INSERT语句中查看我的答案:http://stackoverflow.com/questions/2585723/can-i-assign-a-variable-in -a-sql-stored-procedure/2585918#2585918 – 2010-04-06 15:17:57

+0

@KM:我知道你可以使用'OUTPUT INSERTED'子句用单个语句来完成它。一般而言,我发现单独的陈述更具可读性/可维护性:每项工作都有一个陈述。 – LukeH 2010-04-06 16:08:39

6

你并不需要使用SCOPE_IDENTITY(),使用输出和一个单一的INSERT语句!
这确实需要SQL Server 2005和高达

试试这个:

设置表

CREATE TABLE Test1 (PersonID int identity(1,1), Name varchar(40), Address varchar(60)) 
CREATE TABLE Test2 (PersonID int, product varchar(40),Quantity varchar(5),DueDate datetime) 

创建过程

CREATE PROCEDURE TestSP 
@name varchar(40), 
@address varchar(60), 
@Product varchar(40), 
@Quantity varchar(5), 
@DueDate datetime 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT INTO Test1 
      (Name, Address) 
      OUTPUT INSERTED.PersonID, @Product, @Quantity, @DueDate 
      INTO Test2 
     VALUES 
      (@name, @address) 

END 

测试代码

exec TestSP 'name','address','product',123,'1/1/2010' 
select * from Test1 
select * from Test2 

输出

PersonID Name     Address 
----------- -------------------- ----------------------- 
1   name     address 

(1 row(s) affected) 

PersonID product Quantity DueDate 
----------- --------- -------- ----------------------- 
1   product 123  2010-01-01 00:00:00.000 

(1 row(s) affected) 
+0

同意使用作用域标识,直到有人更改存储过程,导致返回的最后一个值不正确。哎呀 – msarchet 2010-04-06 15:27:57

+0

我以前没见过,谢谢:-) – eftpotrm 2010-04-06 15:29:17

+0

这是一种将项目添加到日志表的简单方法。你甚至可以同时拥有多个OUTPUT语句。另外,如果你删除了INTO,它将返回一个结果集。例如在'INTO Test2'和'VALUES'之间放置'OUTPUT INSERTED。*'。当你运行过程TestSP时,它将插入到两个表中并返回一个包含Test1表的结果集(两个'INSERT's和'SELECT'在一个'INSERT'内!)。 – 2010-04-06 15:41:15

相关问题