【问题标题】:SQL syntax error has occurred发生 SQL 语法错误
【发布时间】:2018-05-06 10:24:12
【问题描述】:

这是我的简单查询:

          my $SQLp = "SELECT MAX([PawnPayments].[CreationTimeDate]) as MaxTransDate
                FROM [PawnSafeDBCE].[dbo].[PawnPayments]
                INNER JOIN [PawnSafeDBCE].[dbo].[PawnPaymentDetails]
                ON [PawnPayments[.[PaymentID] = [PawnPaymentDetails].[PaymentID]
                WHERE [PawnPaymentDetails].[TicketID[ = '$TicketID'
                AND [PawnPaymentDetails].[StoreID] ='$StoreID'

请注意,查询是在 Perl 引擎上编写的。我不断收到一条错误消息:

“您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本对应的手册,了解在 '[PawnPayments].[CreationTimeDate]) as MaxTransDate 附近使用的正确语法:”

我认为错误与括号表示法有关,但不幸的是,由于第 3 方表的构造不佳,我不得不使用这种样式。有什么帮助吗?我错过了什么明显的东西吗?

巨大的编辑:我正在查询的表实际上是在 SQL 服务器上,而不是 MySQL 服务器上!我的数据库在 MySQL 服务器上运行,但这个第 3 方数据库在旧版本的 Microsoft SQL 上运行。

【问题讨论】:

  • 您正在 MySQL 服务器上尝试 SQL-server 语法。括号是 SQL-server 的转义方法。而 dbo 是一个只能在 SQL 服务器中工作的对象......而且你的代码看起来很容易受到 SQL 注入的攻击
  • 仅当您希望它工作时。
  • 您的错误信息清楚地表明了 MySQL。因此,无论您认为哪里涉及到 MSSQL 服务器,您都不是在与它交谈。另外,不要将变量放入您的 SQL 中。请改用 DBI 的占位符。
  • 如果您使用的第 3 方软件仅支持 Microsoft SQL Server,并且无法配置为使用标准标识符分隔符(如 SET QUOTED IDENTIFIER),则无法将其与 MySQL 一起使用.
  • 我还看到您的查询有另一个 Microsoft SQL Server 功能:[PawnSafeDBCE].[dbo].[PawnPayments] 使用Database.Schema.Table 表示法(请参阅docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/…),但 MySQL 不支持。 MySQL 仅支持schema.table。因此,即使您修复了方括号,您的查询也无法在 MySQL 上运行。

标签: mysql sql-server perl delimiter


【解决方案1】:

您说您正在查询 MS SQL 数据库,但错误消息清楚地表明您正在使用 MySQL 数据库或 MySQL 数据库驱动程序。

如果您正在查询 MS SQL 数据库,请修复您的连接字符串。

如果您要查询 MySQL 数据库,请使用与 MySQL 兼容的查询。 MySQL 使用反引号来引用标识符(而不是像 MS SQL 那样的方括号)。

[PawnPayments].[CreationTimeDate]

应该是

`PawnPayments`.`CreationTimeDate`

请注意,由于插入到 SQL 查询中的值引用不正确,您的代码会出现注入错误。 (仅仅在值周围加上引号是不够的!)这些可能会导致您的代码失败,并且它们可能使您容易受到注入攻击。修正引用,或使用可替换的参数。

【讨论】:

    【解决方案2】:

    我不知道为什么你的表和列名周围都有方括号,但它们不是必需的,它们不是标准 SQL。这就是导致您的语法错误的原因。

    my $SQLp = "SELECT MAX(PawnPayments.CreationTimeDate) as MaxTransDate
                FROM PawnSafeDBCE.dbo.PawnPayments
                INNER JOIN PawnSafeDBCE.dbo.PawnPaymentDetails
                ON PawnPayments.PaymentID = PawnPaymentDetails.PaymentID
                WHERE PawnPaymentDetails.TicketID = '$TicketID'
                AND PawnPaymentDetails.StoreID ='$StoreID'";
    

    我还要补充一点,像这样在 SQL 语句中插入变量可能会使您对SQL injection attacks 开放。最好在 SQL 中使用绑定点并使用 execute 的额外参数来填充值(假设您使用的是 DBI)。

    my $SQLp = "SELECT MAX(PawnPayments.CreationTimeDate) as MaxTransDate
                FROM PawnSafeDBCE.dbo.PawnPayments
                INNER JOIN PawnSafeDBCE.dbo.PawnPaymentDetails
                ON PawnPayments.PaymentID = PawnPaymentDetails.PaymentID
                WHERE PawnPaymentDetails.TicketID = ?
                AND PawnPaymentDetails.StoreID = ?";
    
    my $sth = $dbh->prepare($SQLp);
    $sth->execute($TicketID, $StoreID);
    

    更新:正如Bill Karwin 在评论中指出的那样,database.schema.table 语法在 MySQL 数据库中毫无意义。所以我觉得你有点困惑。您收到的错误消息肯定提到了 MySQL,因此您正在使用 DBD::MySQL 连接到 MySQL 服务器 - 但也许您应该改为连接到 MSSQL 服务器。

    如果您向我们展示您的数据库连接代码 - 设置您的 $dbh(或等效)变量的调用,这可能会很有用。

    【讨论】:

    • 感谢您告知我潜在的注入攻击。我从未接触过这些信息。我现在就试试这个方法。
    • MySQL 也不支持Database.Schema.Table 语法。
    • @BillKarwin:好点。我已经更新了我的答案。我认为OP相当混乱!
    • 我认为他们只是在使用一个明显为 Microsoft SQL Server 设计的 Perl 应用程序,并且他们正在尝试将它与 MySQL 一起使用。
    猜你喜欢
    • 2023-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 2015-01-31
    相关资源
    最近更新 更多