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