为什么这个查询不解析?

时间:2018-07-20 15:57:45

标签: mysql sql parsing antlr4

当我通过My​​SQLWorkbench将其提交到MySQL 5.7社区以及MySQL 8社区时,此查询运行良好。

我的语法来自https://github.com/antlr/grammars-v4/tree/master/mysql

以下是查询:

SELECT
    `hr`.`employee`.`FirstName` AS `EmployeeFirstName`
    , `hr`.`employee`.`LastName` AS `EmployeeLastName`
    , `product`.`product`.`Description` AS `ProductDescription`
    , `product`.`unit`.`Unit` AS `Unit`
    , `product`.`product`.`SKU` AS `SKU`
    , `sales`.`transactiondetail`.`Qty` AS `Qty`
    , `product`.`product`.`UnitCost` AS `UnitCost`
    , `product`.`product`.`UnitPrice` AS `UnitPrice`
    , `product`.`manufacturer`.`Manufacturer` AS `Manufacturer`
    , `sales`.`transaction`.`EmployeeNumber` AS `EmployeeNumber`
    , `sales`.`transaction`.`LoyaltyNumber` AS `LoyaltyNumber`
    , `sales`.`transaction`.`StoreNumber` AS `StoreNumber`
    , `store`.`store`.`ZipCode` AS `ZipCode`
    , CAST(
        `sales`.`transaction`.`DateTimeOfTransaction` AS DATE
    ) AS `DateOfTransaction`
    , CAST(
        `sales`.`transaction`.`DateTimeOfTransaction` AS TIME
    ) AS `TimeOfTransaction`
    , CAST(
        CAST(
            `sales`.`transaction`.`DateTimeOfTransaction` AS DATE
        ) AS CHAR CHARSET utf8
    ) AS `DateOfTransactionString`
    , CAST(
        CAST(
            `sales`.`transaction`.`DateTimeOfTransaction` AS TIME
        ) AS CHAR CHARSET utf8
    ) AS `TimeOfTransactionString`
    , WEEKDAY(
        `sales`.`transaction`.`DateTimeOfTransaction`
    ) AS `WeekdayOfTransaction`
    , MONTH(
        `sales`.`transaction`.`DateTimeOfTransaction`
    ) AS `MonthOfTransaction`
    , YEAR(
        `sales`.`transaction`.`DateTimeOfTransaction`
    ) AS `YearOfTransaction`
    , DAYNAME(
        `sales`.`transaction`.`DateTimeOfTransaction`
    ) AS `WeekdayNameOfTransaction`
    , MONTHNAME(
        `sales`.`transaction`.`DateTimeOfTransaction`
    ) AS `MonthNameOfTransaction`
    , `sales`.`transactiondetail`.`TotalPrice` AS `TotalPrice`
FROM
    (
        (
            (
                (
                    (
                        (
                            `sales`.`transaction`
                            JOIN `sales`.`transactiondetail`
                                ON (
                                    (
                                        `sales`.`transaction`.`TransactionID` = `sales`.`transactiondetail`.`TransactionID`
                                    )
                                )
                        )
                        JOIN `hr`.`employee`
                            ON (
                                (
                                    `hr`.`employee`.`EmployeeNumber` = `sales`.`transaction`.`EmployeeNumber`
                                )
                            )
                    )
                    JOIN `product`.`product`
                        ON (
                            (
                                `product`.`product`.`SKU` = `sales`.`transactiondetail`.`SKU`
                            )
                        )
                )
                JOIN `product`.`unit`
                    ON (
                        (
                            `product`.`product`.`UnitID` = `product`.`unit`.`UnitID`
                        )
                    )
            )
            JOIN `store`.`store`
                ON (
                    (
                        `store`.`store`.`StoreNumber` = `sales`.`transaction`.`StoreNumber`
                    )
                )
        )
        JOIN `product`.`manufacturer`
            ON (
                (
                    `product`.`product`.`ManufacturerID` = `product`.`manufacturer`.`ManufacturerID`
                )
            )
    )

这是ANTLR4引发的错误:

  

行1:874输入'选择'没有可行的选择   hremployeeFirstName为   EmployeeFirstNamehremployeeLastName   EmployeeLastNameproductproductDescription   ProductDescriptionproductunitUnit   UnitproductproductSKU   SKUsalestransactiondetailQty   QtyproductproductUnitCost   UnitCostproductproductUnitPrice   UnitPriceproductmanufacturerManufacturer   ManufacturersalestransactionEmployeeNumber   EmployeeNumbersalestransactionLoyaltyNumber   LoyaltyNumbersalestransactionStoreNumber   StoreNumberstorestoreZipCode   ZipCode,广播(salestransactionDateTimeOfTransaction作为日期)   如   DateOfTransaction,广播(salestransactionDateTimeOfTransaction   作为时间)   TimeOfTransaction,广播(广播(salestransactionDateTimeOfTransaction   作为日期)作为char charset'

2 个答案:

答案 0 :(得分:2)

查询完全可以。那个语法坏了。而是使用直接来自MySQL / Oracle的语法作为MySQL Workbench的一部分。它与提供一些C ++代码以使某些谓词起作用的基类一起使用,但是如果需要,您应该很容易将其更新为其他目标语言。

链接语法还允许使用特定的服务器版本来禁用/启用在版本之间更改的某些语言部分。这是您将找到的最完整的语法,它直接来自原始的(和最新的)MySQL yacc grammar(针对ANTLR4进行了优化)。

答案 1 :(得分:1)

您写了

CAST ( ... AS CHAR CHARSET utf8 )

但是根据您使用的语法,应该写出字符集的规范

    CAST ( ... AS CHAR CHARACTER SET utf8 )

显然,MySQL接受CHARSET作为CHARACTER SET的缩写,因此语法对MySQL不正确。

导致错误的生产在1968行:

dataType
    : typeName=(
      CHAR | VARCHAR | TINYTEXT | TEXT | MEDIUMTEXT | LONGTEXT
      )
      lengthOneDimension? BINARY?
      (CHARACTER SET charsetName)? (COLLATE collationName)?        #stringDataType

由于提供的词法分析器能够识别关键字CHARSET,因此您可以通过将CHARACTER SET更改为(CHARACTER SET | CHARSET)来解决该生产问题,但是您可能想搜索{{1 },并进行更改。 (例如,在CHARACTER SET之后的20行中。)该语法中#collectionDataType大约有十二种用法。其中一些接受CHARACTER SET作为别名(如第1636行中所示),但大多数不接受。