SQL Server:动态查询

时间:2014-08-22 22:29:50

标签: sql-server sql-server-2008 tsql

我有一个SQL Server 2008,其表格就像一个哈希映射。基本上,有三列(id, key, val),我需要拉出其他列a, b, c, d, e

目的是基本上选择我需要查询数据的数据库。与此问题类似Using the correct database

我使用强力方法获取SQL。我只是想以更好,更有效的方式做到这一点

这是我想要开始工作的SQL:

CREATE PROCEDURE [dbo].[me] 
    @partitionName VARCHAR(64),
    @id INT
AS
BEGIN
    SET NOCOUNT ON
    SET ROWCOUNT 0

    DECLARE @table as varchar(128)
    DECLARE @sql as nvarchar(4000)
    DECLARE @params as nvarchar(4000)
    DECLARE @s_key as varchar(64)
    DECLARE @paramDefinition as nvarchar(4000)

   DECLARE @a INT
   DECLARE @b VARCHAR(32)
   DECLARE @c VARCHAR(32)
   DECLARE @d VARCHAR(32)
   DECLARE @e VARCHAR(32)

   SET @table = @partitionName + '.dbo.hash_table'

   SET @sql = 
      N'SELECT ' +
      N'    @a = MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END),
            @b = MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END),
            @c = MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END),
            @d = MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END),
            @e = MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END)
    FROM ' + @table + 
    N'WHERE id = ' + CONVERT(VARCHAR(3), @id)

    EXEC sp_executesql @sql

但是,这会产生以下错误

  

必须声明标量变量“@a”

我有一种感觉,我需要做一些事情,例如将@paramsDefinition传递给sp_executesql

但到目前为止,这些都失败了

SET @paramDefinition = '@a INT OUTPUT, '
+ ' @b varchar(32) OUTPUT, '
+ ' @c varchar(32) OUTPUT, '
+ ' @d varchar(32) OUTPUT,' 
+ ' @r varchar(32) OUTPUT'
...
EXEC sp_executesql @sql, @paramDefintions

我得到了

  

'='附近的语法不正确。

这是蛮力方法(有效但击中DB 5次)

SET @key = 'a'
SET @sql = 
N' SELECT @a = val FROM ' + @table +
N' WHERE key = ' + quotename(@key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), @nid)
EXEC sp_executesql @sql, N'@a varchar(32) OUTPUT', @a = @a OUTPUT

SET @key = 'b'
SET @sql = 
N' SELECT @b = val FROM ' + @table +
N' WHERE key = ' + quotename(@key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), @id)
EXEC sp_executesql @sql, N'@b varchar(32) OUTPUT', @b = @b OUTPUT

SET @key = 'c'
SET @sql = 
N' SELECT @c = val FROM ' + @table +
N' WHERE key = ' + quotename(@key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), @id)
EXEC sp_executesql @sql, N'@c varchar(32) OUTPUT', @c = @c OUTPUT

SET @key = 'd'
SET @sql = 
N' SELECT @d = val FROM ' + @table +
N' WHERE key = ' + quotename(@key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), @id)
EXEC sp_executesql @sql, N'@d varchar(32) OUTPUT', @d = @d OUTPUT

SET @key = 'e'
SET @sql = 
N' SELECT @e = val FROM ' + @table +
N' WHERE key = ' + quotename(@key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), @id)
EXEC sp_executesql @sql, N'@e varchar(32) OUTPUT', @e = @e OUTPUT

SELECT @a as [a], @b as [b], @c as [c], @d as [d], @r as [r]

2 个答案:

答案 0 :(得分:1)

您可以尝试使用这样的临时表:

CREATE PROCEDURE [dbo].[me] 

@partitionName VARCHAR(64),
@id INT
AS
BEGIN
SET NOCOUNT ON
SET ROWCOUNT 0

DECLARE @table as varchar(128)
DECLARE @sql as nvarchar(4000)
DECLARE @params as nvarchar(4000)
DECLARE @s_key as varchar(64)
DECLARE @paramDefinition as nvarchar(4000)

  DECLARE @a INT
  DECLARE @b VARCHAR(32)
  DECLARE @c VARCHAR(32)
  DECLARE @d VARCHAR(32)
  DECLARE @e VARCHAR(32)

  SET @table =  @partitionName + '.dbo.hash_table'

  CREATE TABLE #tmp (code varchar(50))

  SET @sql = 
  N'SELECT ' +
  N'    MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END) as [a],
        MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END) as [b],
        MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END) as [c],
        MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END) as [d],
        MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END) as [e]
FROM ' + @table + 
N'WHERE id = ' + CONVERT(VARCHAR(3), @id)

INSERT INTO  #tmp (code)
EXEC sp_executesql @sql

SELECT * from #tmp

希望它有所帮助。

答案 1 :(得分:0)

试试这个......

动态SQL有自己的作用域,存储过程中的变量对动态sql是不可见的,你需要将这些变量声明为sp_execuetsql的第二个参数,因为你要在这些变量中恢复值,你需要将这些变量传递给sp_executesql时,请使用关键字OUTPUT,如下所示

CREATE PROCEDURE [dbo].[me] 
   @partitionName SYSNAME,
   @id            INT
AS
BEGIN
  SET NOCOUNT ON;

    DECLARE @table as varchar(128)
    DECLARE @sql as nvarchar(4000)
    DECLARE @params as nvarchar(4000)
    DECLARE @s_key as varchar(64)
    DECLARE @paramDefinition as nvarchar(4000)

    DECLARE @a INT
    DECLARE @b VARCHAR(32)
    DECLARE @c VARCHAR(32)
    DECLARE @d VARCHAR(32)
    DECLARE @e VARCHAR(32)

 SET @table =  @partitionName + 'hash_table'

SET @sql =  N'SELECT ' +
          N'    @a = MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END),
                @b = MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END),
                @c = MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END),
                @d = MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END),
                @e = MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END)
                FROM dbo.' + QUOTENAME(@table) + 
                N' WHERE id = @id)'

EXEC sp_executesql @sql
                  ,N'@a INT OUTPUT, @b VARCHAR(32) OUTPUT,@b VARCHAR(32) OUTPUT,@c VARCHAR(32) OUTPUT, 
                      @d VARCHAR(32) OUTPUT,@e VARCHAR(32) OUTPUT, @id INT'
                  ,@a OUTPUT
                  ,@b OUTPUT
                  ,@c OUTPUT
                  ,@d OUTPUT
                  ,@e OUTPUT
                  ,@id
END