我试图从某个表中获取所有记录,其中某个字段不是空字符串或null。由于我构建查询的方式,ISNULL
和COALESCE
不是此处的选项。也不能选择更改数据库的模式。
这是我试图检索记录的代码。
using System;
using System.Data.SqlClient;
using System.Linq;
using Dapper;
namespace DapperMCVE
{
internal class UserFinder
{
public static void Main(string[] args)
{
using (var connection = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;Integrated Security=True"))
{
connection.Execute(@"IF NOT EXISTS(SELECT * FROM sys.tables WHERE name = 'Users')
CREATE TABLE Users(NullableUserId varchar(50) NULL) ON [PRIMARY]");
connection.Execute(@"DELETE Users");
connection.Execute(@"INSERT INTO Users(NullableUserId)
VALUES(''), (NULL), ('SteveSmith@fake.com'), ('Morgan@totallyreal.org')");
var parameters = new DynamicParameters();
parameters.Add("UserIdNull", (string)null);
parameters.Add("UserIdBlank", "");
try
{
var users = connection.Query(@"SELECT *
FROM Users
WHERE NullableUserId IS NOT @UserIdNull
AND NullableUserId != @UserIdBlank", parameters);
Console.WriteLine(users.ToList());
}
catch (SqlException e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
}
}
引发的错误是System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near '@UserIdNull'.
我的假设是上面的代码应该复制这个查询:
SELECT *
FROM Users
WHERE NullableUserId IS NOT NULL
AND NullableUserId != ''
但似乎正在做一些接近
的事情SELECT *
FROM Users
WHERE NullableUserId IS NOT 'NULL'
AND NullableUserId != ''
如果我将查询更改为
SELECT *
FROM Users
WHERE ISNULL(NullableUserId, '') != ISNULL(@UserIdNull, '')
它工作正常。不幸的是,我不能在这种情况下使用ISNULL
。
我已在SQL Server 2014和2016中复制了这一点。我们在生产环境中使用2016。
探查器报告正在运行以下命令:
exec sp_executesql N'SELECT *
FROM Users
WHERE NullableUserId IS NOT @UserIdNull
AND NullableUserId != @UserIdBlank',N'@UserIdNull nvarchar(4000),@UserIdBlank nvarchar(4000)',@UserIdNull=NULL,@UserIdBlank=N''
这让我怀疑这可能是SQL Server本身的一个问题?
我尝试过的事情(无济于事):
答案 0 :(得分:3)
您不能使用IS NOT和变量。如果你总是期望null,你可以硬编码NullableUserId IS NOT NULL。 或者使用一些字符串连接创建查询文本
答案 1 :(得分:2)
您不能在sp_executesql或其他任何地方使用IS NOT
和参数
看看这个例子。
此查询从我的表中返回4条记录:
exec sp_executesql
N'SELECT * FROM tblUser WHERE gsm IS NOT null AND gsm != '''''
所以现在我尝试使用两个值的参数,现在我得到一个错误
exec sp_executesql
N'SELECT * FROM tblUser WHERE gsm IS NOT @UserIdNull AND gsm <> @UserIdBlank',
N'@UserIdNull nvarchar(100),@UserIdBlank nvarchar(100)',
@UserIdNull=NULL,@UserIdBlank=N''
但现在我收到了错误
'@ UserIdNull'附近的语法不正确
在没有sp_executesql的情况下执行此操作时会出现相同的错误
declare @UserIdNull nvarchar(100) = null
declare @UserIdBlank nvarchar(100) = ''
SELECT * FROM tblUser WHERE gsm IS NOT @UserIdNull AND gsm <> @UserIdBlank
这会产生相同的错误
因此,唯一的选择是在没有IS NOT
值参数的情况下构建查询或使用ISNULL()
在您构建问题的查询中,您知道何时编写IS NOT
,然后写入参数。
我建议只需编写IS NOT NULL
而不是使用参数
答案 2 :(得分:2)
IS NOT @UserIdNull
真的不是有效的SQL语法.... IS NOT NULL
没问题。这不是一个小巧的问题 - 这只是一个SQL功能:你需要编写合法的SQL。
我的假设是上面的代码应该复制这个查询:
不。它使用参数。语法被保留。 Dapper不会注入文字。这是非常慎重和正确的。 I wrote about this yesterday,正好相反。