【问题标题】:How to execute a stored procedure with parameters?如何执行带参数的存储过程?
【发布时间】:2018-12-20 10:13:54
【问题描述】:

我有一个包含 40 个表的数据库。我想使用单个存储过程从某个表中选择数据。第一个表(TblSPAU1) 有6 列,命名为:ID, COL_SPAU1_EA, COL_SPAU1_EQ, COL_SPAU1_ore, COL_SPAU1_nivel, DateTime。例如,第四个表 (TblSPAU4) 有 6 列:ID, COL_SPAU4_EA, COL_SPAU4_EQ, COL_SPAU4_ore, COL_SPAU4_nivel, DateTime。所以我想要的是从表X中选择DateStartDateStop的数据。到目前为止我所做的是:

USE [DBRapBreaza]
GO
/****** Object:  StoredProcedure [dbo].[PS_SpauOPompa]    Script Date: 12/19/2018 15:48:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[PS_SpauOPompa]

@DataStart datetime,
@DataStop datetime,
@val int
AS
BEGIN
SET NOCOUNT ON;

declare @sql NVARCHAR(max)
declare @col1 varchar
set @col1='ID'
declare @col2 varchar(25) 
set @col2='COL_SPAU'+CONVERT(VARCHAR, @val)+'_EA' 
declare @col3 varchar 
set @col3='DateTime'

set @sql='select [ID]'+@col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between'+CONVERT(VARCHAR(25), @DataStart,121)+ 'and'+CONVERT(VARCHAR(25), @DataStop,121)+';'

END

EXEC sp_sqlexec @sql, N'@DataStart datetime,@DataStop datetime,@val int',  @DataStart, @DataStop, @val

我想从某个表中选择 ID 和第一列。 @val 代表我要从中选择数据的表的编号。 在sp_sqlexec 我有一个工具提示,它说我指定了太多参数。当我执行 EXEC 时,它会抛出这个错误:Msg 137, Level 15, State 2, Line 1. Must declare the scalar variable "@sql". 我的问题是我应该如何执行这个存储过程? 非常感谢!

【问题讨论】:

  • sp_sqlexec 不再受支持,因此您应该考虑使用 sp_executesql。阅读此sommarskog.se/dynamic_sql.html#sp_executesql
  • 我删除了那个工具提示消息,但我仍然收到 Msg 137, Level 15, State 2, Line 1。必须声明标量变量“@sql”错误。我应该在代码的另一部分声明@sql 吗?
  • 将 END 移到批处理的末尾
  • 我把最后一个END移到EXEC之后,但还是出现错误。

标签: sql-server sql-server-2008 stored-procedures parameters dynamic-sql


【解决方案1】:

首先,您的字符串构建中需要一些空格。具体来说,将其更改为:

set @sql= 'select [ID], '+@col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), @DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), @DataStop,121)+''';'

这将使您的 SQL 看起来像这样:

select [ID], COL_SPAU1_EA FROM [DBRapBreaza].[dbo].[TblSPAU1] WHERE DateTime between '2018-12-20 14:18:02.170' and '2018-12-20 14:18:02.170';

与以下相反:

select [ID]COL_SPAU1_EA FROM [DBRapBreaza].[dbo].[TblSPAU1] WHERE DateTime between2018-12-20 14:19:13.167and2018-12-20 14:19:13.167;

缺少的:

  • 第一列后面的逗号
  • 逗号名称之间的空格(语义)
  • 单词后之间有空格
  • 将根据您的参数评估日期的引号
  • between 语句的 where 子句中 and 前后的空格

这就是为什么在测试动态 SQL 时使用PRINT @sql 总是明智的。

然后,将END 移动到脚本的最底部后,将执行更改为:

EXEC sp_executesql  
    @sql, 
    N'@DataStart datetime, @DataStop datetime, @val int',  
    @DataStart, @DataStop, @val

这将为您留下以下代码:

USE [DBRapBreaza]
GO
/****** Object:  StoredProcedure [dbo].[PS_SpauOPompa]    Script Date: 12/19/2018 15:48:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[PS_SpauOPompa]

@DataStart datetime,
@DataStop datetime,
@val int
AS
BEGIN
SET NOCOUNT ON;

declare @sql NVARCHAR(max)
declare @col1 varchar   --missing a length here
declare @col2 varchar(25)
declare @col3 varchar   --missing a length here

set @col1='ID'
set @col2='COL_SPAU'+CONVERT(VARCHAR, @val)+'_EA' 
set @col3='DateTime'

set @sql= 'select [ID], '+@col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), @DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), @DataStop,121)+''';'

--print @sql;


EXEC sp_executesql  
    @sql, 
    N'@DataStart datetime, @DataStop datetime, @val int',  
    @DataStart, @DataStop, @val;

END

值得注意的是,您没有为@col1@col3 指定长度,默认为8,所以要小心。你从来没有使用过这个变量,所以我不确定它的用途是什么。

【讨论】:

  • 为什么不添加;s?
  • 我承认@Hogan 对他们的宽容让我很懒惰。
  • 我知道这种感觉——我指出这一点是因为像 OP 所描述的错误有时是错过它们的结果。
  • 您可以看到任何改进或我错过的任何内容?
  • 哦,是的...我查看的是代码而不是 cmets。对不起。
猜你喜欢
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 2023-04-07
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多