如何使用 @para1 = @para2 等参数执行 Sql 服务器过程

Posted

技术标签:

【中文标题】如何使用 @para1 = @para2 等参数执行 Sql 服务器过程【英文标题】:How to do Sql server procedure using parameters like where @para1 = @para2 【发布时间】:2011-08-10 12:55:21 【问题描述】:

我有一个带有单个 select 语句的过程。我需要创建大约 50 个程序,如下所示..

create procedure foo1 as 
select cityid, cityname from footballteam 

footballteam 在我的所有程序中都很常见,我不想创建 50 个单独的程序,而是想编写如下代码并从我的 c# 页面发送 3 个参数

create procedure foo1 (@id bigint, @name varchar(50), @param bigint)as 
select @id, @name from footballtem where @id =@param

我可以在 sql server 中这样传递吗?/ 怎么做这样的

我是否能够在 sql server 中执行 过程重载,有时我只需要传递两个参数并且我想获得一个特定的值,我将传递三个或更多参数... .

【问题讨论】:

【参考方案1】:

没有;这将对参数值进行比较,并返回参数值。为此,您必须替换调用者的值,例如:

string idColumn = "id", nameColumn = "name";
string tsql = string.Format(@"
create procedure foo1 (@param bigint)
as select [0], [1] from footballtem where [0]=@param", idColumn,nameColumn);

并拥有 50 个 SP;您可以在 TSQL 中做同样的事情,对已替换的字符串使用 sp_ExecuteSQL,但 IMO 最好在应用层执行此操作而不是在数据库内部执行此操作。

还有;质疑您是否真的需要存储过程……那个并没有太大帮助;参数化的 TSQL 查询更简单、同样快速且更易于部署。

【讨论】:

您的意思是在 c# 中创建过程本身?你真的这样做吗。这样够安全吗。 ?而且我不认为使用占位符是提供参数的好方法。 @nandu.com - 参数 (@param) 根本没有被替换。但对于其余的 - 你必须;您不能参数化实际查询本身 - 只有参数。至于在 C# 中创建它 - 您自己添加了 C# 标签 ;p 最终,如何 创建它们并不重要;我个人根本不会创建它们 - 我只会使用参数化查询。我需要一个很好的理由来为此创建一个过程。 @nandu.com 具体来说,您可以在 TSQL 中执行相同的操作并使用 sp_ExecuteSQL 来调用它,但是当您完成此操作时,您可能还没有在第一名 - 执行参数化查询更简单。 我们在团队中遵循一个标准,将 select 语句用作过程而不是 tsql 查询。所以我只需要程序【参考方案2】:

我认为您的要求如下:

create procedure foo1 (@id bitint out, @name bigint out, @param bigint)
as
select @id=cityid, @name=cityname from footballteam where teamname = @param

但是您的问题看起来好像您正在尝试动态更改每个查询的列名。

【讨论】:

【参考方案3】:

我不确定我是否理解正确,但您可以为 T-SQL 中的存储过程参数指定默认值。所以你可以在调用时省略它。

CREATE PROCEDURE Proc1 @param1 int, @param2 int = -1 AS SELECT case when @param2=-1 then somefield else @param2 end as column from sometable where somekeyfield=@param1; GO

【讨论】:

【参考方案4】:

假设 MS SQL Server

MS SQL 服务器不支持过程重载(如 Oracle 所支持的),但支持如下输入和输出参数:

create procedure foo1 (
     @param bigint
    , @id bigint out
    , @name varchar(50) out

   )as 

select 
 @id = fbt.id
,@name = fbt.name 
from 
   footballteam fbt 
where fbt.id =@param

@id 和@name 必须作为正确类型的空值输出参数传入。执行后 (cmd.executeNonQuery) 您可以检查命令对象以获取新的参数值。

我不确定我是否正确阅读了您的问题,但如果我是,那么这应该得到您想要的..

*在问题后添加更好的代码示例 *

//_assumes the following using statements at the top of code file:_
//using System.Data;
//using System.Data.SqlClient;
     public string getTeam(int CityID)
          
             string name;

             using (var cmd = new SqlCommand("foo1",new SqlConnection("myConnectionStringGoesHere")))
             
                cmd.Parameters.Add(new SqlParameter("@param", CityID));
                cmd.Parameters.Add(new SqlParameter("@id", SqlDbType.BigInt)Direction=ParameterDirection.Output);
                cmd.Parameters.Add(new SqlParameter("@name", SqlDbType.VarChar,50)  Direction = ParameterDirection.Output );

                cmd.Connection.Open();
                cmd.ExecuteNonQuery();

                name = cmd.Parameters["@name"].Value.ToString();

                cmd.Connection.Close();

             

             return name;
          

【讨论】:

执行非查询只会返回不受影响的行数。如何从中获取数据集?你能解释一下吗? ExecuteNonQuery 只有 return 行数,是的。但是,该命令维护对参数对象的引用,这些参数对象会随着存储过程的执行而使用值进行更新。它是关于持有对指针而不是值的引用。【参考方案5】:

对于纯 TSQL 答案:

create table footballtem(id int identity(1,1),cityid int, cityname varchar(50))
go
insert footballtem(cityid, cityname) values (123, 'abc')
insert footballtem(cityid, cityname) values (456, 'def')
go
create procedure foo1 (@id sysname, @name sysname, @param bigint) as
declare @sql nvarchar(100) = 'select ' + QUOTENAME(@id) + ','
       + QUOTENAME(@name) + ' from footballtem where '
       + QUOTENAME(@id) + '=@param'
exec sp_ExecuteSql @sql, N'@param bigint', @param
go
exec foo1 'cityid','cityname',123

(归功于Mikael Eriksson re QUOTENAME

请注意,QUOTENAME 使 @name@id 注入安全。

另外请注意,variing 参数 (@param) 不会被注入 - 我们不需要在任何地方进行验证;并且这将允许通过sp_ExecuteSql重复使用查询计划

【讨论】:

我猜你可以使用quotename(@id)quotename(@name) 来处理SQL 注入问题。 @Mikael - 哦,很好。我倾向于首先避免这种情况,但这是解决该问题的好方法 我觉得不错。学分真的应该在这里sommarskog.se/dynamic_sql.html :) 当所有 OP 需要和想要的是两个参数值(实际上只需要一个)时,您仍然返回一个完整的记录集。 @CosCallis er,不...它返回 2 列(根据示例),并按行过滤(根据示例)【参考方案6】:

有一种方法可以在 MSSQL 上进行重载。这是怎么回事:

例如,我们有一个 sp_Personel 过程,它将人员类型作为参数并列出该类型的人员。

CREATE PROCEDURE [dbo].[sp_Personel]
           @PersonelType int
AS
SELECT Name, JoinDate, PersonelType, Salary
FROM Personel
WHERE PersonelType = @PersonelType
END

现在,您需要另一个用于个人加入日期的程序。

CREATE PROCEDURE [dbo].[sp_Personel];2
           @JoinDate datetime
AS
SELECT Name, JoinDate, PersonelType, Salary
FROM Personel
WHERE JoinDate <= @JoinDate 
END

从管理工作室调用第二个程序;

[dbo].[sp_Personel];2 N'9/26/2010'

【讨论】:

以上是关于如何使用 @para1 = @para2 等参数执行 Sql 服务器过程的主要内容,如果未能解决你的问题,请参考以下文章

loadrunner,怎么根据判断结果,执行含有不同参数的代码段

insert into 语句出现错误,不知应该怎么将参数传入数据库?

使用宏进行动态版本选择

python之匿名函数以及在内置函数中的使用

接口测试-postman

Java学习笔记