首页 > 解决方案 > 变量应该被声明

问题描述

我正在使用 T-SQL。目标是将多个文件插入数据库。如果我在没有循环的情况下使用,它工作正常。

在循环中,我总是收到此错误:

@InputXML 应该被声明

我的代码:

IF OBJECT_ID('TEMPDB..#TEMP_FILES') IS NOT NULL 
    DROP TABLE #TEMP_FILES

CREATE TABLE #TEMP_FILES
(
    FileName VARCHAR(MAX),
    DEPTH VARCHAR(MAX),
    [FILE] VARCHAR(MAX)
)
 
INSERT INTO #TEMP_FILES
    EXEC master.dbo.xp_DirTree '\\MyServer\MyFolder\',1,1
    
DELETE FROM #TEMP_FILES WHERE RIGHT(FileName,4) != '.XML'
    
--
SET QUOTED_IDENTIFIER ON 
GO
    
TRUNCATE Table MyTable2

DECLARE @InputXML XML
DECLARE @FILENAME VARCHAR(MAX),@SQL VARCHAR(MAX)
    
WHILE EXISTS(SELECT * FROM #TEMP_FILES)
BEGIN
    SET @FILENAME = (SELECT TOP 1 FileName FROM #TEMP_FILES)
    SET @sql = 'SELECT @InputXML = CAST(x AS XML) FROM OPENROWSET(BULK \\MyServer\MyFolder\'''+ @FILENAME +''', SINGLE_BLOB) AS T(x)
       
    INSERT INTO MyTable2 ([id],[version], [name], [listId], [listCode])
        SELECT 
            product.value(''(@id)[1]'', ''NVARCHAR(10)''), 
            product.value(''(@version)[1]'', ''NVARCHAR(14)''), 
            product.value(''(name[1])'', ''NVARCHAR(255)''),
            product.value(''(listId[1])'', ''NVARCHAR(9)''),
            product.value(''(listCode[1])'', ''NVARCHAR(10)'')
        FROM @InputXML.nodes(''xxx/values/value'') AS X(product)'

    EXEC(@SQL)
    
    DELETE FROM #TEMP_FILES 
    WHERE FileName = @FILENAME
END

标签: sql-servertsql

解决方案


您需要在动态 SQL 中声明变量(不应该nvarcharvarchar。您还应该使用QUOTENAME以确保文件名没有问题:

DECLARE @sql nvarchar(max) = N'
DECLARE @InputXML XML;
SELECT @InputXML = CAST(x AS XML) FROM OPENROWSET(BULK ' + QUOTENAME(N'\\MyServer\MyFolder\' + @FILENAME, '''') + N', SINGLE_BLOB) AS T(x)
       
INSERT INTO MyTable2 ([id],[version], [name], [listId], [listCode])
    SELECT 
    product.value(''(@id)[1]'', ''NVARCHAR(10)''), 
    product.value(''(@version)[1]'', ''NVARCHAR(14)''), 
    product.value(''(name[1])'', ''NVARCHAR(255)''),
    product.value(''(listId[1])'', ''NVARCHAR(9)''),
    product.value(''(listCode[1])'', ''NVARCHAR(10)'')
   
    FROM @InputXML.nodes(''xxx/values/value'') AS X(product)'

不过,我会说,我敦促您找到另一种将文件加载到 SQL Server 中的方法。不建议使用Dynamic OPENROWSET,尤其是来自用户输入的。批量插入或 BCP 可能是一种选择。


推荐阅读