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_Tsql - Fatal编程技术网

Sql server 如何将表名作为变量传递给存储过程

Sql server 如何将表名作为变量传递给存储过程,sql-server,tsql,Sql Server,Tsql,我继承了一堆存储过程,基本上是一个shell,在引号中是一个巨大的动态SQL,包含大量的条件、计算和case语句,但是这个动态SQL中FROM子句中的表名每季度都会发生变化 在我被激怒之前,我想简单地说我继承了它们,它是如何在我面前被设计的。因此,每季度调用这些存储过程时,都会将实际表名作为参数传递,然后动态SQL将表名连接起来 这种方法的问题在于,随着每次运行时间的推移,先前的设计者只是简单地附加了更多的标准作为条件和计算。但是动态SQL字符串有一个长度限制。此外,维护和调试变得非常困难 CR

我继承了一堆存储过程,基本上是一个shell,在引号中是一个巨大的动态SQL,包含大量的条件、计算和case语句,但是这个动态SQL中
FROM
子句中的表名每季度都会发生变化

在我被激怒之前,我想简单地说我继承了它们,它是如何在我面前被设计的。因此,每季度调用这些存储过程时,都会将实际表名作为参数传递,然后动态SQL将表名连接起来

这种方法的问题在于,随着每次运行时间的推移,先前的设计者只是简单地附加了更多的标准作为条件和计算。但是动态SQL字符串有一个长度限制。此外,维护和调试变得非常困难

CREATE PROCEDURE .....
    @dynSQL1 = 'SELECT......
            FROM' + strTblName + '
            WHERE.....   
            GROUP BY....' 
     ...
     EXEC @dynSQL1
 GO
然而,我想问大家,有没有一种方法可以将这个带有这个巨大动态SQL字符串的存储过程转换成一个基于参数化表名的普通存储过程

我的主要目标有两个,一是摆脱动态SQL这样的长字符串,二是更容易维护和调试。我想,在SQL Server 2016/2017及以后版本的SQL Server中,这个问题得到了解决

非常感谢您的想法和建议

~G

因此,每季度调用这些存储过程时,都会将实际表名作为参数传递,然后动态SQL将表名连接起来

您可以将该过程更改为对其他存储过程进行编码,而不是运行动态SQL。例如:

CREATE PROCEDURE admin.RegenerateProcedures @tableName
as
begin

    declare @ddl nvarchar(max) = '
create or alter procedure dbo.SomeProc
as
begin
           SELECT......
            FROM dbo.' + quotename(@tableName) +  '
            WHERE.....   
            GROUP BY....
end
' 
     EXEC ( @ddl )
. . .
end
 GO
因此,每季度调用这些存储过程时,都会将实际表名作为参数传递,然后动态SQL将表名连接起来

您可以将该过程更改为对其他存储过程进行编码,而不是运行动态SQL。例如:

CREATE PROCEDURE admin.RegenerateProcedures @tableName
as
begin

    declare @ddl nvarchar(max) = '
create or alter procedure dbo.SomeProc
as
begin
           SELECT......
            FROM dbo.' + quotename(@tableName) +  '
            WHERE.....   
            GROUP BY....
end
' 
     EXEC ( @ddl )
. . .
end
 GO

不能参数化对象,它必须是文本。这意味着您必须使用动态SQL并安全地注入值(上面没有)。然后,您需要使用sys.sp_executesql执行并将任何其他变量的参数传递给它。看看我在哪里介绍了很多你需要考虑的问题。也许你可以用一个同义词来表示表格,然后每季度简单地更改一次同义词?但听起来生成正确查询的逻辑远比交换表名复杂得多,因此您最好将精力花在其他地方。在64位服务器上,动态SQL字符串的大小限制为2 GB,即nvarchar(max)的最大大小,因此我对此不感兴趣。在32位实例上没有任何不同,@Piotr,仍然是2GB,或10亿字符。@Tomasito表和索引分区在SQL Server 2016 SP1及更高版本中都可用,包括Azure SQL数据库。您不能参数化对象,它必须是文本。这意味着您必须使用动态SQL并安全地注入值(上面没有)。然后,您需要使用sys.sp_executesql执行并将任何其他变量的参数传递给它。看看我在哪里介绍了很多你需要考虑的问题。也许你可以用一个同义词来表示表格,然后每季度简单地更改一次同义词?但听起来生成正确查询的逻辑远比交换表名复杂得多,因此您最好将精力花在其他地方。在64位服务器上,动态SQL字符串的大小限制为2 GB,即nvarchar(max)的最大大小,因此我对此不感兴趣。在32位实例上没有任何不同,@Piotr,仍然是2GB,或10亿字符。@Tomasito表和索引分区在SQL Server 2016 SP1及更高版本中都可用,包括Azure SQL数据库。
EXEC(@DDL)
不是一个好主意。它不支持动态语句的参数化。SQL Server不支持DDL中的参数。我不是这么说的。。。我说过,使用
EXEC(@SQL)
或(
EXEC(@DDL)
EXEC(@somevariablecontainingsql)
)不促进动态语句的参数化。使用sys.sp_executesql
EXEC(@DDL)
不是一个好主意。它不支持动态语句的参数化。SQL Server不支持DDL中的参数。我不是这么说的。。。我说过,使用
EXEC(@SQL)
或(
EXEC(@DDL)
EXEC(@somevariablecontainingsql)
)不促进动态语句的参数化。使用sys.sp\u executesql。