将值传递到 T-SQL 中的存储过程

Posted

技术标签:

【中文标题】将值传递到 T-SQL 中的存储过程【英文标题】:Pass value into stored procedure in T-SQL 【发布时间】:2021-12-30 03:30:54 【问题描述】:

我正在尝试将变量 @date 传递到我的 T-SQL 命令(在 Synapse 中的 DB 中)。我想要它做的是按用户定义的给定日期从表中删除数据。

这是我的脚本,当我在其中定义日期时,它工作得很好:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [DPIT].[proc_nhs_delete_by_date] @date datetime, @TableName sysname AS

BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON

DECLARE @SchemaName sysname;

SET @SchemaName = N'DPIT';

DECLARE @SQL nvarchar(MAX);
SET @SQL = N'DELETE FROM ' + QUOTENAME(@SchemaName) + N'.' + QUOTENAME(@TableName) + N' WHERE datum = @date;';
EXEC sys.sp_executesql @SQL, N'@date datetime', @date

END

但是当我执行这个存储过程并将参数传递给它时,我得到了以下错误:

Parse error at line: 3, column: 1: Incorrect syntax near 'EXEC'.

这是产生错误的代码:

DECLARE @return_value int

EXEC    @return_value = [DPIT].[proc_nhs_delete_by_date]
        @date = N'20231021',
        @TableName = sluzba_G

SELECT  'Return Value' = @return_value

GO

您知道问题可能出在哪里吗?我倾向于认为问题在于 Synapse 可能不支持 EXEC 命令,我将不得不以某种方式使用sys.sp_executesql,但老实说,我不知道该怎么做。

非常感谢您的帮助!

【问题讨论】:

@PanagiotisKanavos 感谢您的意见!不幸的是,这是一个我们需要尽快完成的项目,我们将从 Power Apps 发送输入。它在其他项目中对我们有用(虽然在 Synapse 中没有),所以我们希望使用经过验证的方法,因为我们没有时间寻求更复杂的解决方案。 为什么要在这里使用“动态”SQL,而对象的名称是静态的;您为变量分配一个静态值。不需要这种逻辑。 正如Larnu 所说,当你最终执行一个显示DELETE from schema.Table where date=@date 的字符串时,为什么要首先使用该存储过程?使用硬编码的架构和表?只需执行最后的语句 我不会使用 SQL Server 标记来回答有关 Azure Synapse Analytics 的问题。它与“常规” SQL Server 有很多不同 @PanagiotisKanavos - 他们使用的产品不支持该语法 (truncate with partitions)。 docs.microsoft.com/en-us/sql/t-sql/statements/… - 可能还有其他选择,但我不太了解 【参考方案1】:

除了动态 SQL,您遇到的问题是工具。在 Synapse 专用 SQL 池(SQW 数据仓库)中,您不能使用 return 以默认 SSMS 方式调用存储过程。

改变这个:

DECLARE @return_value int

EXEC    @return_value = [DPIT].[proc_nhs_delete_by_date]
        @date = N'20231021',
        @TableName = sluzba_G

SELECT  'Return Value' = @return_value

GO

到这里:

EXEC    [DPIT].[proc_nhs_delete_by_date]
        @date = N'20231021',
        @TableName = sluzba_G

它应该可以正常工作。

【讨论】:

这正是问题所在,谢谢乔尔:) 另外,很多人表示应该避免使用动态 SQL(我主要使用 OOP,因此我倾向于在 SQL 中使用相同的逻辑并对所有内容进行参数化)。您能推荐一些专门针对动态 SQL 问题的文献吗?谢谢:)【参考方案2】:

@Larnu 的评论需要突出显示:

当对象的名称是静态的时,为什么在这里使用“动态”SQL;您为变量分配一个静态值。不需要这个逻辑

您的代码过于复杂且可怕(动态 SQL 应该让每个人都感到恐惧!)。

您的代码可以简化为:

ALTER PROCEDURE DPIT.proc_nhs_delete_by_date (
 @date datetime
)
  AS
BEGIN
  SET NOCOUNT ON;

  DELETE
  FROM   dbo.some_table
  WHERE  datum = @date
  ;
END
;

【讨论】:

只有当有人想要允许人们执行该操作而不实际授予他们对表的 DELETE 权限时才需要这样做。

以上是关于将值传递到 T-SQL 中的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL存储过程 - 无法将输出值分配给变量

如何将值的“数组”传递给我的存储过程?

SQL server T-SQL存储过程

使用 JPA 2.1 / Hibernate 4 将值列表传递给存储过程

SqlServerSqlServer编程语言T-SQL的存储过程

将 Dictionary<string,int> 传递给存储过程 T-SQL