动态 SQL:带有 @param 的 OPENROWSET 和 INSERT 到 @Table
Dynamic SQL: OPENROWSET with @param and INSERT into @Table
我正在尝试使用 OPENROWSET
和循环中的 @param
插入 @table
参数。我改编了以下代码:This Answer,它演示了如何使用 Dynamic SQL 插入参数。
代码:
DECLARE @BuildTimes TABLE (
BuildTableName VARCHAR(max) NULL
,BuildDate DATE NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);
WHILE (@days <=30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
SET @sql='INSERT INTO @BuildTimes
SELECT *
FROM OPENROWSET(
''SQLNCLI'',
''SERVER=localhost;Trusted_Connection=yes;'',
''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'
PRINT @sql
EXEC(@sql)
SET @days = @days + 1
END
SELECT * FROM @BuildTimes
错误:
Msg 1087, Level 15, State 2, Line 9
Must declare the table variable "@BuildTimes"
我试过 运行 OPENROWSET 作为非动态 SQL 没有参数,它一切正常。我做错了什么?
您的变量 table @BuildTimes
无法在 Dynamic SQL 中访问。即使您声明它并使用动态 SQL 加载它,您也无法读取动态范围之外的结果。
一种解决方案是使用临时 table 而不是可变的:
IF OBJECT_ID('tempdb..#BuildTimes') IS NOT NULL
DROP TABLE #BuildTimes
CREATE TABLE #BuildTimes (
BuildTableName VARCHAR(max) NULL
,BuildDate DATE NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);
WHILE (@days <=30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
SET @sql='INSERT INTO #BuildTimes
SELECT *
FROM OPENROWSET(
''SQLNCLI'',
''SERVER=localhost;Trusted_Connection=yes;'',
''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'
PRINT @sql
EXEC(@sql)
SET @days = @days + 1
END
SELECT * FROM #BuildTimes
table 可以在 EXEC
外部读取,因为它是在外部创建的,并且可以在内部访问,因为它保持在同一会话中。
作为旁注,只要您期望一组已知的列,请避免使用 *
,这样,如果在 SELECT
的基础 table 上添加新列, 你 INSERT
不会坏的。
为什么要使用动态 SQL 而不是只使用 INSERT INTO
?
DECLARE @BuildTimes table (BuildTableName varchar(MAX) NULL,
BuildDate date NULL);
DECLARE @days int = 0;
DECLARE @startDate date = GETDATE();
DECLARE @buildDate date = GETDATE();
WHILE (@days <= 30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
INSERT INTO @BuildTimes (BuildTableName,
BuildDate)
EXEC log.BuildTimes @buildDate;
SET @days = @days + 1;
END;
SELECT BuildTableName,
BuildDate
FROM @BuildTimes;
我发现对于这种情况我根本不需要 Dynamic SQL / OPENROWSET。以下代码产生所需的结果:
DECLARE @BuildTimes TABLE (
BaseTableName VARCHAR(max) NULL
,BuildDate DATE NULL
,StartDateTime DATETIME NULL
,FinishDateTime DATETIME NULL
,TimeTakenMinutes BIGINT NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @thisBuildDate DATE = GETDATE();
WHILE (@days <=30)
BEGIN
SET @thisBuildDate = DATEADD(day, -1*@days, @startDate);
PRINT @thisBuildDate
INSERT INTO @BuildTimes
EXEC [LOG].[BuildTimes] @buildDate = @thisBuildDate
SET @days = @days + 1
END
SELECT * FROM @BuildTimes
GO
我正在尝试使用 OPENROWSET
和循环中的 @param
插入 @table
参数。我改编了以下代码:This Answer,它演示了如何使用 Dynamic SQL 插入参数。
代码:
DECLARE @BuildTimes TABLE (
BuildTableName VARCHAR(max) NULL
,BuildDate DATE NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);
WHILE (@days <=30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
SET @sql='INSERT INTO @BuildTimes
SELECT *
FROM OPENROWSET(
''SQLNCLI'',
''SERVER=localhost;Trusted_Connection=yes;'',
''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'
PRINT @sql
EXEC(@sql)
SET @days = @days + 1
END
SELECT * FROM @BuildTimes
错误:
Msg 1087, Level 15, State 2, Line 9
Must declare the table variable "@BuildTimes"
我试过 运行 OPENROWSET 作为非动态 SQL 没有参数,它一切正常。我做错了什么?
您的变量 table @BuildTimes
无法在 Dynamic SQL 中访问。即使您声明它并使用动态 SQL 加载它,您也无法读取动态范围之外的结果。
一种解决方案是使用临时 table 而不是可变的:
IF OBJECT_ID('tempdb..#BuildTimes') IS NOT NULL
DROP TABLE #BuildTimes
CREATE TABLE #BuildTimes (
BuildTableName VARCHAR(max) NULL
,BuildDate DATE NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);
WHILE (@days <=30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
SET @sql='INSERT INTO #BuildTimes
SELECT *
FROM OPENROWSET(
''SQLNCLI'',
''SERVER=localhost;Trusted_Connection=yes;'',
''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'
PRINT @sql
EXEC(@sql)
SET @days = @days + 1
END
SELECT * FROM #BuildTimes
table 可以在 EXEC
外部读取,因为它是在外部创建的,并且可以在内部访问,因为它保持在同一会话中。
作为旁注,只要您期望一组已知的列,请避免使用 *
,这样,如果在 SELECT
的基础 table 上添加新列, 你 INSERT
不会坏的。
为什么要使用动态 SQL 而不是只使用 INSERT INTO
?
DECLARE @BuildTimes table (BuildTableName varchar(MAX) NULL,
BuildDate date NULL);
DECLARE @days int = 0;
DECLARE @startDate date = GETDATE();
DECLARE @buildDate date = GETDATE();
WHILE (@days <= 30)
BEGIN
SET @buildDate = DATEADD(day, -1*@days, @startDate);
INSERT INTO @BuildTimes (BuildTableName,
BuildDate)
EXEC log.BuildTimes @buildDate;
SET @days = @days + 1;
END;
SELECT BuildTableName,
BuildDate
FROM @BuildTimes;
我发现对于这种情况我根本不需要 Dynamic SQL / OPENROWSET。以下代码产生所需的结果:
DECLARE @BuildTimes TABLE (
BaseTableName VARCHAR(max) NULL
,BuildDate DATE NULL
,StartDateTime DATETIME NULL
,FinishDateTime DATETIME NULL
,TimeTakenMinutes BIGINT NULL
)
DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @thisBuildDate DATE = GETDATE();
WHILE (@days <=30)
BEGIN
SET @thisBuildDate = DATEADD(day, -1*@days, @startDate);
PRINT @thisBuildDate
INSERT INTO @BuildTimes
EXEC [LOG].[BuildTimes] @buildDate = @thisBuildDate
SET @days = @days + 1
END
SELECT * FROM @BuildTimes
GO