Передайте переменную TABLE в sp_executesql
Я пытаюсь передать переменную 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 ответа
Если вы используете 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
Дальнейшие обсуждения здесь.
Хорошо, это даст мне то, что я хочу, но, конечно, не красиво:
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!?
С уважением Алекс
Хотя это может не дать прямого ответа на ваш вопрос, оно должно решить вашу проблему в целом.
Вы действительно можете записать результаты выполнения хранимой процедуры во временную таблицу:
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
С уважением, Тим
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
Так называемые 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