【问题标题】:MySQL error 1064: search query not working as expectedMySQL 错误 1064:搜索查询未按预期工作
【发布时间】:2017-07-29 11:52:50
【问题描述】:

我正在尝试编写用于在表上搜索的查询,但我收到了一般的 1064 MySQL 语法错误。我没有发现我的查询有什么问题……事实上,我还有另一个查询,它工作正常。

查询在 Go 中使用 SQL 驱动程序,所有 ? 将在查询运行之前转换为值。

这是我的错误:

错误 1064:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在 'SELECT tax.* 附近使用的正确语法 从税 加入用户税 ON user_tax.tax_id = tax.id WHERE u' 在第 3 行

例如,这是有效的查询:

SELECT tax.*
FROM tax
JOIN user_tax
    ON user_tax.tax_id = tax.id
WHERE user_tax.user_id = ?
    AND tax.deleted_at IS NULL
    AND user_tax.deleted_at IS NULL

上面的查询将查找给定用户的所有税务记录。

现在我正在尝试进行完全相同的查询,但现在它是一个“搜索”查询。它接收一个搜索字符串并在税表的namerate 列中查找它。就是这样:

SET @searchString = '%?%';

SELECT tax.*
FROM tax
JOIN user_tax
    ON user_tax.tax_id = tax.id
WHERE user_tax.user_id = ?
    AND tax.deleted_at IS NULL
    AND user_tax.deleted_at IS NULL
    AND tax.name LIKE @searchString
        OR tax.rate LIKE @searchString

这是代码中的查询:

var taxes []Tax
err := r.db.Select(&taxes, `
    SET @query = '%?%';

    SELECT tax.*
    FROM tax
    JOIN user_tax
        ON user_tax.tax_id = tax.id
    WHERE user_tax.user_id = ?
        AND tax.deleted_at IS NULL
        AND user_tax.deleted_at IS NULL
        AND tax.name LIKE @query
            OR tax.rate LIKE @query
`, q, userId)

【问题讨论】:

  • 你的接口只允许传入一个查询。我建议你学习为你正在使用的接口使用合适的参数。
  • 哦,很好,我的意思是用? 代替%s。刚刚在我的代码和问题中更新。仍然出现同样的错误。
  • 还将@query 更改为@searchString,因为这可能会造成混淆,我并没有尝试将查询放入查询中。
  • 在哪里 user_tax.user_id = ?这是什么?表示?
  • 为什么你使用?你是在使用php pdo还是其他东西来查询db?

标签: mysql sql go


【解决方案1】:

如果要避免多次绑定同一个值,可以在交叉连接子查询中绑定一次,然后重复使用该值:

SELECT tax.*
FROM tax
JOIN user_tax
    ON user_tax.tax_id = tax.id
CROSS JOIN (SELECT ? as q) sub
WHERE user_tax.user_id = ?
    AND tax.deleted_at IS NULL
    AND user_tax.deleted_at IS NULL
    AND (tax.name LIKE sub.q
         OR tax.rate LIKE sub.q)

现在只需将%s% 绑定为第一个参数。

【讨论】:

  • @Lansana 我看到了您想要的简单解决方案。不错!
  • @Lansana - 我预计不会出现任何性能问题。子查询应该只执行一次。
  • @PaulSpiegel 这个查询给了我一个错误。 Error 1267: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation 'like' -- 使用与您相同的查询。
  • 这很糟糕。看起来您的连接排序规则与列的排序规则不匹配。我不确定在这种情况下该怎么做,因为我总是尝试在任何地方使用 UTF-8。
【解决方案2】:

我不明白为什么要做SET @query 并在其中传递它时您可以通过使用? 使用绑定参数来做到这一点。

所以这是解决方案(我不熟悉go,所以如果go 代码有问题,请见谅):

var taxes []Tax
query := "%something%youre%looking%for%"
err := r.db.Select(&taxes, `

    SELECT tax.*
    FROM tax
    JOIN user_tax
        ON user_tax.tax_id = tax.id
    WHERE user_tax.user_id = ?
        AND tax.deleted_at IS NULL
        AND user_tax.deleted_at IS NULL
        AND (
              tax.name LIKE ? 
              OR 
              tax.rate LIKE ?
            )

`, q, userId, query, query)

或者试试这个(我不确定它是否会起作用):

var taxes []Tax
query := "something"
err := r.db.Select(&taxes, `
    SET @query = CONCAT('%', ?, '%');

    SELECT tax.*
    FROM tax
    JOIN user_tax
        ON user_tax.tax_id = tax.id
    WHERE user_tax.user_id = ?
        AND tax.deleted_at IS NULL
        AND user_tax.deleted_at IS NULL
        AND (
              tax.name LIKE @query
              OR 
              tax.rate LIKE @query
            )

`, q, query, userId)

【讨论】:

  • 是的,这行得通...但是有没有办法不必通过query N 次?如果我有 30 列怎么办......这就是为什么我试图在查询中设置变量所以我只需要绑定到一个东西然后重新使用它。
  • @Lansana 你在开玩笑吗?当您有严格的 sql 查询时,为什么要考虑动态时刻?
  • 这来自于 SQL 经验最少的人,但通常在编程中我可以记住一个值并使用它来保持干燥。我猜这不是它在 SQL 中的工作方式?
  • @Lansana sql 查询很简单。您可以在go 部分进行 DRY,但查询必须严格形成以避免意外
  • @Lansana 您可以在交叉连接的子查询中绑定一次,然后重复使用它。
【解决方案3】:

MySQL 报告的语法错误包含魔术词“检查与您的 MySQL 服务器版本相对应的手册,以了解在 ' 附近使用正确的语法”,然后是查询的尾随部分'不适合已经解析并发现正确的前导部分。

当错误消息中报告的查询部分看起来不正确时,通常在它之前缺少某些内容。

在您的情况下,似乎什么都没有丢失,这导致了一个单一的结论:您尝试运行两个查询(正确地由 ; 分隔)但是您用来向服务器发送查询的库不知道这一点并且认为这只是一个查询。同样的情况也发生在连接的另一端,MySQL 服务器仅将在第一次查询后发现的所有内容报告为“语法错误”(及其终止 ;)。

不要在单个调用中发送两个查询或使用允许在同一字符串中进行多个查询的调用(如果库提供了这样的调用)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2012-11-13
    相关资源
    最近更新 更多