如何使用 @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,怎么根据判断结果,执行含有不同参数的代码段