23

我正在尝试将 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

我不能直接进入临时变量(对吗?)......

任何帮助表示赞赏!

4

5 回答 5

12

如果您使用的是 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

在这里进一步讨论。

于 2011-01-01T17:10:32.713 回答
3

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

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!?

问候亚历克斯

于 2010-11-24T07:58:51.773 回答
2

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

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

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    

问候,蒂姆

于 2011-11-25T18:20:24.443 回答
0
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
于 2012-05-16T04:32:31.003 回答
0

所谓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
于 2020-06-29T23:19:47.090 回答