sql-server - 以表名作为参数的存储过程

标签 sql-server stored-procedures dynamic-sql

我尝试更新一个存储过程,该过程运行良好,无需使用 sp_executesql。我现在希望将表名称作为参数,因为我有许多具有相同结构的表,并且不想为每个表创建新的存储过程。

我遇到的问题是这个版本似乎需要所有参数,而前一个版本接受任意数量的参数。例如,如果我删除所有 WHERE 参数并仅使用 @TableName 参数,则它可以正常工作。我尝试寻找一个例子,但我找不到这样的东西。所有解析表名的示例都只有该参数。

CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = 'SELECT * FROM [' + @TableName + ']' + 
    'WHERE ([Square] LIKE ''' + @Square + ''' OR ''' + @Square + ''' IS NULL)' + 
    'AND ([Location] = ''' + @Location + ''' OR ''' + @Location + ''' IS NULL)' +
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql
END

请提出建议。

最佳答案

建议1: 使用 QUOTENAME() 处理表名的正确转义。

建议 2:您正在将参数的值插入到 @sql 中。不要那样做。相反,您应该使用参数化的 sql。

建议 3:通过有条件地构建查询的 WHERE 子句来消除 OR 逻辑。

 CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = N'SELECT * FROM ' + QUOTENAME(@TableName ) + 
    ' WHERE 1=1 '
    IF  @Square IS NOT NULL
      SET @sql = @sql + ' AND ([Square] LIKE   @Square )'  -- still patameterized
   IF @Location IS NOT NULL
      SET @sql = @sql + N'  AND ([Location] = @Loc )'
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql, N'@Square nvarchar(100), @Loc nvarchar(100)...', @square=@square, @loc=@location  -- the param names can be the same or different, sp_executesql has it's own scope.
END

Sp_executesql除了执行普通sql之外还可以执行参数化sql。它是客户端库用来执行参数化代码的底层系统存储过程。例如,如果添加了任何参数,System.Data.SqlClient.SqlCommand 将调用 sp_executesql。它的非典型之处在于它接受可变数量的参数。 msdn 文档 sp_executesql提供了一些很好的信息,但不清楚。捕获 SQL 探查器中的事件是查看 sp_executesql 运行情况的最简单方法。

关于sql-server - 以表名作为参数的存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17118929/

相关文章:

sql - 在 select 语句中插入多个值的值

php - Mysql存储过程的查询优化

sql - 使用单元测试项目进行CLR SQL存储过程测试

sql - 使用 SQL CASE 语句动态更改要选择的表

python - 使用 SqlAlchemy 执行原始查询(在 SQL-Server 数据库和 Pymssql 上)时,传递的参数无法识别并引发 SQL 错误

sql - 将带有 Access 前端的 CSV 文件导入 SQL Server

postgresql - 将字符串转换为列名

sql - R 中的动态 SQL 查询(WHERE)

sql-server - 在 SQL 语句中没有返回准确的结果

postgresql - PL/pgSQL 函数中的可选参数