Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用列作为参数的动态SQL。ISNULL()函数是';我不再工作了_Sql Server - Fatal编程技术网

Sql server 使用列作为参数的动态SQL。ISNULL()函数是';我不再工作了

Sql server 使用列作为参数的动态SQL。ISNULL()函数是';我不再工作了,sql-server,Sql Server,我试图使用一个存储过程,它包含参数,应该用作列名。举个例子 Select * from table1 where @columnparameter = 'test' 我发现实现它的一种方法是使用动态sql,到目前为止,它正在工作。但我还想使用ISNULL函数,检查另一个参数是否为null,如果为null,则应返回指定列的所有值 以前(在使用动态sql语句之前)我使用了以下行 [...] AND (table1.userId = ISNULL(@userId, table1.userId)) A

我试图使用一个存储过程,它包含参数,应该用作列名。举个例子

Select * from table1 where @columnparameter = 'test'
我发现实现它的一种方法是使用动态sql,到目前为止,它正在工作。但我还想使用ISNULL函数,检查另一个参数是否为null,如果为null,则应返回指定列的所有值

以前(在使用动态sql语句之前)我使用了以下行

[...]
AND (table1.userId = ISNULL(@userId, table1.userId))
AND (table1.fileId = ISNULL(@fileId, table1.fileId))
这对我来说很好,但是因为我使用动态sql,所以当我执行存储过程时,我不再得到任何结果。 我发现,当我删除“ISNULL”行时,至少会得到结果

现在,声明如下:

'AND (q.userId = ISNULL('+@l_userId+', q.userId))
AND (q.fileId = ISNULL('+@l_docId+', q.fileId))'
AND (userId = ISNULL('value_userId', q.userId))
AND (fileId = ISNULL('value_docId', q.fileId))
'AND (userId = ISNULL(q.userId, '''+@l_userId+'''))
 AND (fileId = ISNULL(q.fileId, '''+@l_docId+'''))'
在这种情况下,我根本没有得到任何结果。似乎根本没有执行sql命令

但我也试过:

'AND (q.userId = '+ISNULL(@l_userId, 'q.userId')+')
AND (q.userId ='+ISNULL(@l_docId, 'q.fileId')+')'
在这种情况下,当参数为null时,我至少会得到结果,但一旦它们有值,我就会得到错误消息,即参数的值是无效的列名

我也尝试了一些不同的方法,但都有误导性,并导致了各种例外情况等

对我来说,使用动态sql是相当混乱的,因为有大量的引号:D

这样做:

'AND (userId = ISNULL('''+@l_userId+''', q.userId))
 AND (fileId = ISNULL('''+@l_docId+''', q.fileId))'
您需要使用单引号的转义序列括起变量
''''
,因此在生成的SQL中,它将如下所示:

'AND (q.userId = ISNULL('+@l_userId+', q.userId))
AND (q.fileId = ISNULL('+@l_docId+', q.fileId))'
AND (userId = ISNULL('value_userId', q.userId))
AND (fileId = ISNULL('value_docId', q.fileId))
'AND (userId = ISNULL(q.userId, '''+@l_userId+'''))
 AND (fileId = ISNULL(q.fileId, '''+@l_docId+'''))'
我不知道哪个值真的可以为null,但因为这是一个查询,所以最好先编写表列,而不是像这样编写变量:

'AND (q.userId = ISNULL('+@l_userId+', q.userId))
AND (q.fileId = ISNULL('+@l_docId+', q.fileId))'
AND (userId = ISNULL('value_userId', q.userId))
AND (fileId = ISNULL('value_docId', q.fileId))
'AND (userId = ISNULL(q.userId, '''+@l_userId+'''))
 AND (fileId = ISNULL(q.fileId, '''+@l_docId+'''))'
这样做:

'AND (userId = ISNULL('''+@l_userId+''', q.userId))
 AND (fileId = ISNULL('''+@l_docId+''', q.fileId))'
您需要使用单引号的转义序列括起变量
''''
,因此在生成的SQL中,它将如下所示:

'AND (q.userId = ISNULL('+@l_userId+', q.userId))
AND (q.fileId = ISNULL('+@l_docId+', q.fileId))'
AND (userId = ISNULL('value_userId', q.userId))
AND (fileId = ISNULL('value_docId', q.fileId))
'AND (userId = ISNULL(q.userId, '''+@l_userId+'''))
 AND (fileId = ISNULL(q.fileId, '''+@l_docId+'''))'
我不知道哪个值真的可以为null,但因为这是一个查询,所以最好先编写表列,而不是像这样编写变量:

'AND (q.userId = ISNULL('+@l_userId+', q.userId))
AND (q.fileId = ISNULL('+@l_docId+', q.fileId))'
AND (userId = ISNULL('value_userId', q.userId))
AND (fileId = ISNULL('value_docId', q.fileId))
'AND (userId = ISNULL(q.userId, '''+@l_userId+'''))
 AND (fileId = ISNULL(q.fileId, '''+@l_docId+'''))'

从您提供的数据很难说您是否可以从常规Sql中获得更好的结果(即,不创建动态语句),但根据我的经验,通常是可能的。值得思考

无论如何,要回答您的问题,请尝试以下方法:

'AND (q.userId = '+ISNULL('''' + @l_userId +'''', 'q.userId')+')
AND (q.userId ='+ISNULL('''' + @l_docId +'''', 'q.fileId')+')'

利用将字符串与空值串联将导致空值的事实,
ISNULL
函数仍将执行它需要执行的操作,并且sql将是有效的。

从您提供的数据很难说您是否可以从常规sql中获得更好的结果(即,不创建动态语句),但根据我的经验,这通常是可能的。值得思考

无论如何,要回答您的问题,请尝试以下方法:

'AND (q.userId = '+ISNULL('''' + @l_userId +'''', 'q.userId')+')
AND (q.userId ='+ISNULL('''' + @l_docId +'''', 'q.fileId')+')'

利用将字符串与空值串联将导致空值的事实,
ISNULL
函数仍将执行它需要执行的操作,并且sql将是有效的。

如果变量不为空,则只将条件构建到语句中会更有效,如:

DECLARE @SQL NVARCHAR(MAX);

-- The base statement
SET @SQL = 'SELECT * FROM table1 WHERE @columnparameter = ''test''';

-- Only append the extra conditions if the variables are not null
IF @l_userId IS NOT NULL
    SET @SQL += ' AND table1.userId = ' + @l_userId;

IF @l_docId IS NOT NULL
    SET @SQL += ' AND table1.fileId = ' + @l_docId;

如果变量不为null,则只将条件构建到语句中会更有效,如:

DECLARE @SQL NVARCHAR(MAX);

-- The base statement
SET @SQL = 'SELECT * FROM table1 WHERE @columnparameter = ''test''';

-- Only append the extra conditions if the variables are not null
IF @l_userId IS NOT NULL
    SET @SQL += ' AND table1.userId = ' + @l_userId;

IF @l_docId IS NOT NULL
    SET @SQL += ' AND table1.fileId = ' + @l_docId;

改用sp_executesql。它支持类型化参数:

set @sql = N'...
AND (table1.userId = ISNULL(@userId, table1.userId))
AND (table1.fileId = ISNULL(@fileId, table1.fileId))
'

exec sp_executesql @sql, N'@userId varchar(100), @fileid varchar(100)', @l_userId, @l_docid

更少的
和sql注入的机会。

改用sp_executesql。它支持类型化参数:

set @sql = N'...
AND (table1.userId = ISNULL(@userId, table1.userId))
AND (table1.fileId = ISNULL(@fileId, table1.fileId))
'

exec sp_executesql @sql, N'@userId varchar(100), @fileid varchar(100)', @l_userId, @l_docid

更少的
和sql注入的机会。

什么数据类型是
@l\u userId
@l\u docId
?如果某些数字转换为nvarchar,ISNULL的行为不会改变。问题是(几乎总是)您构造了一个字符串连接的查询,但却弄错了。混合使用参数和动态sql是。。。至少说来很奇怪。为什么不直接使用参数化查询呢?在参数上使用
ISNULL
有什么意义?您是否试图创建一个带有“可选”参数的“神奇”存储过程?你所做的保证是非常缓慢的——通过对字段应用函数,你可以防止使用任何索引。此外,执行计划在存储过程的第一次执行时计算和缓存。这意味着您的存储过程将以不适当的执行计划结束。为什么不简单地使用ORM,让它生成正确、快速的动态查询呢?
@l_userId
@l_docId
是什么数据类型?如果某些数字转换为nvarchar,ISNULL的行为不会改变。问题是(几乎总是)您构造了一个字符串连接的查询,但却弄错了。混合使用参数和动态sql是。。。至少说来很奇怪。为什么不直接使用参数化查询呢?在参数上使用
ISNULL
有什么意义?您是否试图创建一个带有“可选”参数的“神奇”存储过程?你所做的保证是非常缓慢的——通过对字段应用函数,你可以防止使用任何索引。此外,执行计划在存储过程的第一次执行时计算和缓存。这意味着您的存储过程将以不适当的执行计划结束。为什么不简单地使用ORM,让它生成正确和快速的动态查询?
'
应该是
'
-您需要转义内部
'
。OP可能正在尝试创建“可选”筛选器,ie参数,如果为空,则不过滤任何内容。问题是这样的构造速度非常慢,因为它们阻止了索引的使用,并导致执行计划缓慢。当然,解决方案只是使用一个ORM来处理所有这些问题。“可选筛选器”是不可配置的,对我来说不起作用。使用这种方法,我也没有得到任何结果。但佐哈尔的解决方案做到了。无论如何非常感谢你的建议:)编辑:啊,没有看到这篇文章的其他评论。我认为,佐哈尔是对的,缺少一个引号。
'
应该是