我正在尝试从自引用表中构建面包屑。该查询在MySQL Workbench中运行得非常好,但在应用程序中运行时,查询失败并带有
Unhandled Exception: MySql.Data.MySqlClient.MySqlException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= Parent
FROM
Codebook
WHERE
id = _id
) as ParentId,
' at line 6
我已经为我的服务器版本寻找了正确的语法(Percona Server(GPL),Release rel30.2,Revision 38.2)。我正在托管GoDaddy的数据库。 查询如下:
var query = @"SELECT T2.* FROM (
SELECT
@r as _id,
(
SELECT
@r := Parent
FROM
Codebook
WHERE
id = _id
) as ParentId,
@l := @l + 1 as lvl
FROM
Codebook
WHERE
@r <> 0
) T1
JOIN Codebook T2
ON T1._id = T2.Id
ORDER BY T1.lvl DESC";
return Query(query, new
{
r = childId,
l = 0
});
其中Query(query
是dapper的包装器方法,它使用存储在网站appsettings中的连接字符串。
我做错了什么?无论如何我可以做得更好吗?
答案 0 :(得分:2)
您的dapper参数@l
和@r
以及MySQL user variables @l
和@r
的语法相同。 Dapper可能会在每种情况下解决变量,导致无意义的陈述,如......
0 := 0 + 1 as lvl
@l
{li> childId := Parent
@r
...因此MySQLException。
要解决此问题,只需将MySQL用户变量重命名为某个值,该值与此查询中的任何一个Dapper参数都不匹配。
我能够在本地环境中重现此MySQLException,并验证更改用户变量可以解决问题。
重现MySQLException :同时命名@l
。
private int givenSameNames_ExpectMySQLException(IDbConnection conn)
{
return conn.Query<int>("SELECT @l := @l + 1", new
{
l = 1
}).FirstOrDefault();
}
要产生良好的结果:只需将@l
重命名为@test
。
private int givenDifferentNames_ExpectSuccess(IDbConnection conn)
{
return conn.Query<int>("SELECT @test := @l + 1", new
{
l = 1
}).FirstOrDefault();
}
为@l
和@r
执行此操作 - dapper参数和用户变量需要不同的名称。
Allow User Variables=True
在您使用MySQL连接器的MySQL连接字符串中包含Allow User Variables=True
。解决命名问题后,如果发现错误,请注意需要定义MySQL用户变量,请检查此问题。默认情况下这是错误的,用户变量在查询中不起作用,除非这是真的。