【问题标题】:Pass a TABLE variable to sp_executesql将 TABLE 变量传递给 sp_executesql
【发布时间】:2011-05-14 14:44:38
【问题描述】:

我正在尝试将 TABLE 变量传递给 sp_executesql 过程:

 DECLARE @params NVARCHAR(MAX)
 SET @params = '@workingData TABLE ( col1 VARCHAR(20),
                col2 VARCHAR(50) )'

 EXEC sp_executesql @sql, @params, @workingData

我得到错误:

Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'TABLE'.

我尝试在“TABLE”之后省略列规范。我还尝试将表声明为动态 SQL 中的变量。但是没有运气...

在我看来,在此过程中不允许将 TABLE 变量作为参数传递吗?顺便说一句:我正在运行 MSSQL2008 R2。

我对使用像 #workingData 这样的本地临时表不感兴趣,因为我从另一个过程加载工作数据:

INSERT INTO @workingData
     EXEC myProc @param1, @param2

我不能直接在临时变量中做这件事(对吗?)...

任何帮助表示赞赏!

【问题讨论】:

  • @workingdata 变量的内容是什么?
  • 所有变量的内容是什么?我不认为这完全符合您的期望。
  • 我使用@workingData TABLE 存储来自另一个过程的结果,该过程返回多个过程使用的通用结果集。这是为了减少冗余代码:INSERT INTO @workingData EXEC someProc
  • 这个链接可能对stackoverflow.com/questions/7329996/…有帮助

标签: sql dynamic sp-executesql


【解决方案1】:

如果您使用的是 SQL Server 2008,要将表变量传递给存储过程,您必须首先定义表类型,例如:

CREATE TYPE SalesHistoryTableType AS TABLE
(                     
    [Product] [varchar](10) NULL,                
    [SaleDate] [datetime] NULL,                
    [SalePrice] [money] NULL
)
GO

或使用存储在数据库中的现有表类型。

使用这个查询来定位现有的表类型

SELECT * FROM sys.table_types

要在存储过程中使用,请将输入变量声明为表:

CREATE PROCEDURE usp_myproc
(
    @TableVariable SalesHistoryTableType READONLY
)
AS BEGIN
    --Do stuff     

END
GO

在传递给存储过程之前填充表变量:

DECLARE @DataTable AS SalesHistoryTableType
INSERT INTO @DataTable
SELECT * FROM (Some data)

调用存储过程:

EXECUTE usp_myproc
@TableVariable = @DataTable

进一步讨论here。

【讨论】:

  • +1 虽然我认为他没有尝试对在调用范围内可见的表变量进行更改?
  • 我需要它来处理传递给 so_executeSql 的动态 SQL。我试图在上面的@params 规范参数中将参数声明为表类型。我没有直接调用存储过程。 . .
  • 您提供的链接已失效。还有其他资源吗?
【解决方案2】:

好的,这会得到我想要的,但肯定不漂亮:

DECLARE @workingData TABLE ( col1 VARCHAR(20),
        col2 VARCHAR(20) )

    INSERT INTO @workingData
        EXEC myProc

    /* Unfortunately table variables are outside scope
       for the dynamic SQL later run. We copy the 
       table to a temp table. 
       The table variable is needed to extract data directly
       from the strored procedure call above...
    */
    SELECT * 
    INTO #workingData
    FROM @workingData


        DECLARE @sql NVARCHAR(MAX)
    SET @sql = 'SELECT * FROM #workingData'

    EXEC sp_executesql @sql

必须有更好的方法将此临时结果集传递到 sp_executesql!?

问候 亚历克斯

【讨论】:

  • 否决了这个答案,只是因为不需要在表之间复制数据。您可以直接插入到临时表中(我敢肯定您很久以前就知道了,但是为了 SO,这个答案很差)。
【解决方案3】:

虽然这可能无法直接回答您的问题,但应该可以整体解决您的问题。

您确实可以将存储过程的执行结果捕获到临时表中:

INSERT INTO #workingData
EXEC myProc 

因此,将您的代码更改为如下所示:

CREATE TABLE #workingData ( col1 VARCHAR(20),    
    col2 VARCHAR(20) )    

INSERT INTO #workingData    
    EXEC myProc    

DECLARE @sql NVARCHAR(MAX)    
SET @sql = 'SELECT * FROM #workingData'    

EXEC sp_executesql @sql    

问候, 蒂姆

【讨论】:

  • 要记住的一点是,表定义中的数据类型和从 SP 返回的结果集必须匹配。
  • 刚刚意识到我可能迟到了大约一年的时间。 :) 对不起!
  • 这是临时表,不是表变量。
  • @gotqn OP 提到他们想使用表变量,因为他们认为他们无法插入临时表/变量,这就是为什么我提供这个作为可能的解决方案,因为它确实是使用临时表时可能。
【解决方案4】:
Alter PROCEDURE sp_table_getcount 
 @tblname nvarchar(50) ,
 @totalrow int output 
AS
BEGIN

Declare @params nvarchar(1000)
Declare @sql nvarchar(1000)
set @sql = N'Select @cnt= count(*) From @tbl'
set @params = N'@tbl nvarchar(50) , @cnt int OUTPUT'
Exec sp_executesql @sql , @params ,@tbl=@tblname ,  @cnt = @totalrow OUTPUT   
END
GO

请注意,由于对象超出范围,上述代码将无法作为表格工作。它会给您错误:必须声明表格变量。为了解决这个问题,我们可以执行以下操作。

Alter PROCEDURE sp_table_getcount 
 @tblname nvarchar(50) ,
 @totalrow int output 
AS
BEGIN

Declare @params nvarchar(1000)
Declare @sql nvarchar(1000)
set @sql = N'Select @cnt= count(*) From dbo.' + @tblname
set @params = N'@cnt int OUTPUT'
Exec sp_executesql @sql , @params , @cnt = @totalrow OUTPUT   
END
GO

【讨论】:

    【解决方案5】:

    所谓的TableType 很棘手。 @Alex 版本应该可以工作。但是,为了简化和提高性能,请检查 sys.tables 以获取匹配的表名,同时不影响安全性和性能。

    在这里

    create proc [dbo].Test11 
    @t1 AS nvarchar(250), @t2 nvarchar(250)
    AS 
    BEGIN
    SET nocount ON; 
    DECLARE @query AS nvarchar(MAX)
    if exists (select * from sys.tables where name = @t1) and 
        exists (select * from sys.tables where name = @t2)
    begin
        SET @query = N'select * FROM '+ @t1 + N' join ' + @t2 + N' ON ...' ;
        select 'Safe and fast'
        print @query
        exec sp_executesql @query
    
    end
    else
        select 'Bad, no way Jose.'
    
    SET nocount OFF; 
    END
    GO
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 2023-03-30
      • 2020-01-24
      • 2015-12-07
      • 2012-02-13
      • 2014-09-05
      • 2011-10-13
      相关资源
      最近更新 更多