Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在SQL Server数据库中创建和使用“out”参数_Sql Server - Fatal编程技术网

Sql server 如何在SQL Server数据库中创建和使用“out”参数

Sql server 如何在SQL Server数据库中创建和使用“out”参数,sql-server,Sql Server,我正在开发一个C桌面应用程序。我想使用存储过程insert查询将新记录添加到数据表中。我需要返回主键,它是一个identity insert bigint,以避免再次往返数据库。我在MS文件中搜索了几个小时,没有找到任何关于如何设置存储过程的out参数或如何获取返回值的信息。您需要的是一个输出参数。我不是C开发人员,所以我省略了C方面的内容,并链接了一个答案: --Sample Table CREATE TABLE dbo.YourTable (ID bigint IDENTITY,

我正在开发一个C桌面应用程序。我想使用存储过程insert查询将新记录添加到数据表中。我需要返回主键,它是一个identity insert bigint,以避免再次往返数据库。我在MS文件中搜索了几个小时,没有找到任何关于如何设置存储过程的out参数或如何获取返回值的信息。

您需要的是一个输出参数。我不是C开发人员,所以我省略了C方面的内容,并链接了一个答案:

--Sample Table
CREATE TABLE dbo.YourTable (ID bigint IDENTITY,
                            SomeColumn varchar(20));

GO
--Sample SP
CREATE PROC dbo.InsertYourTable @SomeColumn varchar(20), @ID bigint OUTPUT AS
BEGIN

    DECLARE @IDt table (ID bigint);

    INSERT INTO dbo.YourTable(SomeColumn)
    OUTPUT inserted.ID INTO @IDt
    VALUES(@SomeColumn);

    SET @ID = (SELECT ID FROM @IDt);
END;

GO
--Sample EXEC of proc and PRINT of OUTPUT value of ID
DECLARE @SomeColumn varchar(20) = 'abc', @ID bigint;

EXEC dbo.InsertYourTable @SomeColumn = @SomeColumn,
                         @ID = @ID OUTPUT;

PRINT @ID;
用这个,我认为c应该是:

cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@SomeColumn",SqlDbType.VarChar,20);
cmd.Parameters["@SomeColumn"].Value = MyColumn;
cmd.Parameters.Add("@ID",SqlDbType.int).Direction = ParameterDirection.Output;

我的印象是你正试图通过三次往返旅行,如下所示:

INSERT => SELECT to get key => OTHER INSERT using previous key
两岁

INSERT returns the key => OTHER INSERT using previous key
我们可以做得更好

解决此问题的一种方法是从C发送sql字符串中的多个命令。因此,您最终会得到类似的结果,从而达到避免额外往返数据库的目的:

string sql = @"
   DECLARE @ID int; 
   EXEC InsertProcedure; 
   SELECT @ID = scope_identity(); 
   INSERT INTO OtherTable VALUES (@ID);";

using (var cn = new SqlConnection("connection string"))
using (var cmd = new SqlCommand(sql, cn))
{
    cn.Open();
    cmd.ExecuteNonQuery();
}
或者,您可能只希望在应用程序中使用该键,这样您就可以继续使用该记录,并通过新的聚集索引值进行快速查找。在这种情况下,您仍然可以这样做:

string sql = @"
   DECLARE @ID int; 
   EXEC InsertProcedure; 
   SELECT scope_identity();";

using (var cn = new SqlConnection("connection string"))
using (var cmd = new SqlCommand(sql, cn))
{
    cn.Open();
    return (int)cmd.ExecuteScalar();
}
只需注意存储过程本身是否有任何未解析的select查询,在这种情况下,您需要使用ExecuteReader及其NextResult方法在select查询结果之间前进


当然,这可能比实际代码更重要,您需要插入新数据的参数,但这提供了一般概念。

在insert上使用OUTPUT子句非常好,如果您需要在多行批处理中捕获标识值,那么这是非常必要的。然而,对于SQL初学者来说,代码稍微复杂一些,对于这个特定的问题,它可能会与存储过程的输出参数混淆,这是一个完全不相关的概念

但是,对于单行插入,该函数非常有效,而且使用起来更简单

以下是使用SCOPE_IDENTITY的一个版本:

CREATE PROC dbo.InsertYourTable @SomeColumn varchar(20), @ID bigint OUTPUT AS
BEGIN

INSERT INTO dbo.YourTable(SomeColumn)
VALUES(@SomeColumn);

SET @ID = SCOPE_IDENTITY();
END;

在你们的帮助下,我终于明白了。我对存储过程进行了如下修改:

//存储过程


使用存储过程而不是直接执行INSERT有什么原因吗?使用函数而不是过程,可以使用返回值。Dai,存储过程更快,有助于防范sql注入攻击。不是万无一失的,但它有帮助。存储过程并不比其他类型的查询快。这是一个经常被引用的神话。参数化查询可以防止注入攻击。您不需要使用存储过程来实现这一点。这很酷,但它没有回答如何使用存储过程的输出参数的问题。这是最有帮助的,让我能够找到答案。下面我的答案中适用于我的代码。谢谢你给我指出了正确的方向。欢迎@user1818434,请将其标记为答案,以便将来的读者知道答案是有用的。此外,你还因为把一个问题作为答案而名声大噪。
```` -- Add the parameters for the stored procedure here
````@Vendorcode nvarchar(17) = ''
````, @Name nvarchar(60) = ''
````...
````, @ID bigint output  --<<<<<<<<Added this line
````AS
````BEGIN
````    -- SET NOCOUNT ON added to prevent extra result sets from
````    -- interfering with SELECT statements.
````    SET NOCOUNT ON;
````    -- Insert statements for procedure here
````INSERT INTO APVendorShipTo
````        (Vendorcode, [Name], ...)
````VALUES  (@Vendorcode, @Name,...)

````Select @ID = SCOPE_IDENTITY(); -- <<<<<<<< Added this line
````END
*//end Stored Procedure*
----------


----------

*//C# Code in Desktop App*

````try
````{
````string connString = AdoHelper.ConnectionString;
````var myConnection = new SqlConnection(connString);
````var myCommand = new SqlCommand();
````using (myConnection)
````{
```` myConnection.Open();
```` myCommand.Connection = myConnection;
```` myCommand.CommandType = CommandType.StoredProcedure;
```` myCommand.CommandTimeout = 540;
```` myCommand.CommandText = "APVendorShipToAddNew";     
```` myCommand.Parameters.AddWithValue(parameterName: "@Vendorcode", value:   
this.txtAcctNo.Text);
```` myCommand.Parameters.AddWithValue(parameterName: "@Name", value: this.txtShipName.Text);
-- left out the rest of the parameters
--//Added the line below to retrieve the Identity Insert value from the query
````myCommand.Parameters.Add("@ID", SqlDbType.BigInt).Direction = ParameterDirection.Output;

````myCommand.ExecuteNonQuery();

--//Added next line to convert the returned value to a usable value in my program.
````liID = Convert.ToInt64(myCommand.Parameters["@ID"].Value);

````MessageBox.Show(Convert.ToString(liID)); 
--//Showed correct value Now available to  my code

````return true;
````}