存储过程,将表名作为参数传递
Posted
技术标签:
【中文标题】存储过程,将表名作为参数传递【英文标题】:Stored procedure, pass table name as a parameter 【发布时间】:2010-07-27 18:47:02 【问题描述】:我有大约六个通用但相当复杂的存储过程和函数,我想以更通用的方式使用它们。
理想情况下,我希望能够将表名作为参数传递给过程,因为目前它是硬编码的。
我所做的研究表明,我需要将我的过程中的所有现有 SQL 转换为使用动态 SQL,以便从参数中拼接动态表名,但是我想知道是否有更简单的方法来引用表换一种方式?
例如:
SELECT * FROM @MyTable WHERE...
如果是这样,我如何从表名中设置@MyTable 变量?
我使用的是 SQL Server 2005。
【问题讨论】:
这些表是如何/在哪里创建或存储的?它们是其他查询的结果吗? 正如 marc_s 所说,升级到 SQL 2008。在处理单个表的大量更新时,表值参数非常棒。 请仔细阅读他的问题。尽管有问题标题,但他试图传递一个表名(不是表)。 【参考方案1】:动态 SQL 是执行此操作的唯一方法,但如果需要,我会重新考虑您的应用程序的体系结构。 SQL 不太擅长“通用”代码。当它被设计和编码以执行单个任务时,它的效果最好。
从 TableA 中选择与从 TableB 中选择不同,即使选择语句看起来相同。可能有不同的索引、不同的表大小、数据分布等。
您可以生成自己的存储过程,这是一种常用方法。有一个代码生成器,可以为您需要的表创建各种选择存储过程。每个表都有自己的 SP,然后您可以将其链接到您的应用程序中。
我已经在 T-SQL 中编写了这些类型的生成器,但是您可以使用大多数编程语言轻松地做到这一点。这是非常基本的东西。
再补充一点,因为 Scott E 提出了 ORM……您还应该能够将这些存储过程与最复杂的 ORM 一起使用。
【讨论】:
谁能提供更多关于编写 SQL 生成器的信息?您如何部署等,并确保生成的代码重复的所有位置保持同步? IMO 生成的代码应全部检入您的源代码控制系统。然后,您可以针对特定表等特定的内容修改它们。您运行的任何部署都应使用源代码控制系统中的文件。您可以使用像 Red Gate 的 SQLCompare(和 SQLDataCompare)这样的工具来确保各种 DB 是同步的。他们在 www.red-gate.com。他们还有一个新的 SQL 源代码控制产品和一个部署打包程序。【参考方案2】:您必须使用动态 sql。但不要那样做!最好使用 ORM。
【讨论】:
添加 ORM 会增加非常高的开销。当你在它的时候不要用锤子把钉子钉进去,我有这块非常大的巨石你可以使用。 我愿意随时承担动态 sql 的安全风险。对于大多数简单的查询,像 linq-to-sql 这样的东西几乎不会增加开销。此外,“非常高水平的开销”是相当主观的,你不觉得吗?我猜有点像说“不要使用动态 sql”!【参考方案3】:EXEC(N'SELECT * from ' + @MyTable + N' WHERE ... ')
【讨论】:
动态 SQL 通常不是“最佳的”,但不要听那些说永远不要使用它的人。它有它的位置。【参考方案4】:您可以使用动态 Sql,但首先检查对象是否存在,除非您可以 100% 信任该参数的来源。由于 SQL Server 无法为不同的参数重复使用相同的执行计划,因此可能会影响性能。
IF OBJECT_ID(@tablename, N'U') IS NOT NULL
BEGIN
--dynamic sql
END
【讨论】:
【参考方案5】:ALTER procedure [dbo].[test](@table_name varchar(max))
AS
BEGIN
declare @tablename varchar(max)=@table_name;
declare @statement varchar(max);
set @statement = 'Select * from ' + @tablename;
execute (@statement);
END
【讨论】:
以上是关于存储过程,将表名作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章
通过将表名作为参数传递,使用 oracle 中的存储过程从表中搜索数据