如果我在“ FROM”之后写上tablename
,则查询有效。如果我使用select语句的结果,查询将无法解决。有解决方法吗?
我已经尝试将tablename
解析为存储过程的输出,但是在没有收到错误的情况下,我似乎无法在存储过程或函数中使用exec
ALTER PROCEDURE [dbo].[EDOFA_TABLE]
(
@DTCODE nvarchar(max) = null
,@DTAMPO nvarchar(max) = null
,@DTNDOS float = null
,@DTTFAC nvarchar(max) = null
,@DTCDEB nvarchar(max) = null
,@DTNDEB float = null
,@DTDAPP float = null
)
AS
BEGIN
INSERT INTO EDOFA (DTCODE
,DTAMPO
,DTNDOS
,DTTFAC
,DTCDEB
,DTNDEB
,DTDAPP)
SELECT DTCODE
,DTAMPO
,DTNDOS
,DTTFAC
,DTCDEB
,DTNDEB
,DTDAPP
FROM (SELECT max(name) FROM sys.tables WHERE name like 'EDOFA%')
WHERE DTCODE = @DTCODE
OR DTAMPO = @DTAMPO
OR DTNDOS = @DTNDOS
OR DTTFAC = @DTTFAC
OR DTCDEB = @DTCDEB
OR DTNDEB = @DTNDEB
OR DTDAPP = @DTDAPP
END
关键字where附近的语法不正确
答案 0 :(得分:2)
正如我在评论中所述,“这不是SQL的工作方式。您不能用表达式,变量名等替换对象。它必须是基本的;您需要使用参数化的动态SQL。” 。我相信这就是你所追求的。
ALTER PROCEDURE [dbo].[EDOFA_TABLE] (@DTCODE nvarchar(MAX) = NULL,
@DTAMPO nvarchar(MAX) = NULL,
@DTNDOS float = NULL,
@DTTFAC nvarchar(MAX) = NULL,
@DTCDEB nvarchar(MAX) = NULL,
@DTNDEB float = NULL,
@DTDAPP float = NULL)
AS
BEGIN
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'INSERT INTO dbo.EDOFA (DTCODE,' + NCHAR(13) + NCHAR(10) +
N' DTAMPO,' + NCHAR(13) + NCHAR(10) +
N' DTNDOS,' + NCHAR(13) + NCHAR(10) +
N' DTTFAC,' + NCHAR(13) + NCHAR(10) +
N' DTCDEB,' + NCHAR(13) + NCHAR(10) +
N' DTNDEB,' + NCHAR(13) + NCHAR(10) +
N' DTDAPP)' + NCHAR(13) + NCHAR(10) +
N'SELECT DTCODE,' + NCHAR(13) + NCHAR(10) +
N' DTAMPO,' + NCHAR(13) + NCHAR(10) +
N' DTNDOS,' + NCHAR(13) + NCHAR(10) +
N' DTTFAC,' + NCHAR(13) + NCHAR(10) +
N' DTCDEB,' + NCHAR(13) + NCHAR(10) +
N' DTNDEB,' + NCHAR(13) + NCHAR(10) +
N' DTDAPP' + NCHAR(13) + NCHAR(10) +
N'FROM dbo.' + QUOTENAME((SELECT MAX([name]) FROM sys.tables WHERE name LIKE 'EDOFA%')) + NCHAR(13) + NCHAR(10) +
N'WHERE DTCODE = @DTCODE' + NCHAR(13) + NCHAR(10) +
N' OR DTAMPO = @DTAMPO' + NCHAR(13) + NCHAR(10) +
N' OR DTNDOS = @DTNDOS' + NCHAR(13) + NCHAR(10) +
N' OR DTTFAC = @DTTFAC' + NCHAR(13) + NCHAR(10) +
N' OR DTCDEB = @DTCDEB' + NCHAR(13) + NCHAR(10) +
N' OR DTNDEB = @DTNDEB' + NCHAR(13) + NCHAR(10) +
N' OR DTDAPP = @DTDAPP;';
DECLARE @Params nvarchar(MAX) = N'@DTCODE nvarchar(MAX),' +
N'@DTAMPO nvarchar(MAX),' +
N'@DTNDOS float,' +
N'@DTTFAC nvarchar(MAX),' +
N'@DTCDEB nvarchar(MAX),' +
N'@DTNDEB float,' +
N'@DTDAPP float';
--PRINT @SQL; --Your best friend
EXEC sp_executesql @SQL, @Params, @DTCODE, @DTAMPO, @DTNDOS, @DTTFAC, @DTCDEB, @DTNDEB, @DTDAPP;
END;
我构建了一个动态语句,并将其放入@SQL
中;并确保我使用QUOTENAME
正确引用动态对象名称。然后,我构建参数并将它们全部传递给我们sp_executesql
的动态语句。
如果遇到问题,请取消注释最好的朋友(并注释掉EXEC
)并调试打印的SQL。
答案 1 :(得分:0)
您的from子句返回标量,但未命名。同样,from子句中的子查询也需要别名。这就是导致您得到错误的原因。
添加别名后,还会收到其他错误。例如DTAMPO
不是FROM子句返回的列
答案 2 :(得分:0)
您不能在SQL中动态包含标识符,但可以包含常量值。为此,请像这样使用sp_executesql
:
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = '
INSERT INTO EDOFA (DTCODE, DTAMPO, DTNDOS, DTTFAC, DTCDEB, DTNDEB, DTDAPP)
SELECT DTCODE, DTAMPO, DTNDOS, DTTFAC, DTCDEB, DTNDEB, DTDAPP
FROM [table]
WHERE DTCODE = @DTCODE OR
DTAMPO = @DTAMPO OR
DTNDOS = @DTNDOS OR
DTTFAC = @DTTFAC OR
DTCDEB = @DTCDEB OR
DTNDEB = @DTNDEB OR
DTDAPP = @DTDAPP';
-- Replace the table name because, alas, we cannot parameterize that
SET @SQL = REPLACE(@SQL,
'[table]',
(SELECT max(name) FROM sys.tables WHERE name like 'EDOFA%')
);
-- Pass everything else as parameters
EXEC sp_executesql @SQL,
N'
@DTCODE nvarchar(max),
@DTAMPO nvarchar(max),
@DTNDOS float,
@DTTFAC nvarchar(max),
@DTCDEB nvarchar(max),
@DTNDEB float,
@DTDAPP float',
@DTCODE=@DTCODE, @DTAMPO=@DTAMPO, @DTNDOS=@DTNDOS, @DTTFAC=@DTTFAC,
@DTCDEB=@DTCDEB, @DTNDEB=@DTNDEB, @DTDAPP=@DTDAPP;
END;
编写代码可能会比较麻烦,但是在将值传递到SQL查询中时,使用参数无疑是最佳实践。