【问题标题】:SQL Server Execution Plan AmbiguitySQL Server 执行计划歧义
【发布时间】:2018-07-11 06:11:50
【问题描述】:

问题 - 消息 8114,级别 16,状态 5,第 1 行 将数据类型 nvarchar 转换为数值时出错。 下面是 SQL Server 中的查询

SELECT FIELD_VALUE,
  FREQUENCY_COUNT
FROM Table1 IFNV
INNER JOIN Table2 IFV
ON IFNV.FIELD_KEY = IFV.FIELD_KEY
INNER JOIN Table3 IFVSD
ON IFVSD.FUNCTION_KEY       = IFNV.FUNCTION_KEY
WHERE IFVSD.PROFILE_RUN_KEY = 78
AND IFV.FIELD_NAME          = 'EMPLOYEE_ID'
AND
  CASE
    WHEN IFV.IS_VIRTUAL = 0
    THEN IFV.RECORD_NAME
    ELSE IFNV.RULE_NAME
  END = 'EMPLOYEES'
  AND FIELD_VALUE IS NOT NULL
ORDER BY FREQUENCY_COUNT DESC,
CAST(FIELD_VALUE AS NUMERIC(6,0)) DESC;

当数据库中没有表时不会发生此问题,即最近在数据库中添加了表和数据。 仅当这些表中存在大量数据时才会发生这种情况。 (当我们清除数据库并重新创建所有内容时,不会出现此错误,但遗憾的是我们无法每次都清除数据库并重新创建)。不知道为什么它不是第一次发生

进一步分析发现,在SQL Server中,是先做Casting操作,再做WHERE子句。

有什么方法可以在不清除数据库的情况下克服这个执行流程?

Trying Not Like operator

UnsortedOutput

【问题讨论】:

  • 问题很可能出在您的数据上。您可以包含来自FIELD_VALUE 列的一些数据吗?此外,您可能想更改您的标题,因为这个问题似乎与执行计划没有任何关系。
  • 你的服务器版本是多少?如果 2012 或更高版本使用 TRY_CONVERT 而不是 CAST。 docs.microsoft.com/en-us/sql/t-sql/functions/…
  • @TimBiegeleisen FIELD_VALUE 的数据类型是 nvarchar。该表有 FIELD_NAME、FIELD_VALUE 和其他列。一些数据是 FIELD_VALUE 是“Samson”、102、104、“RAHUL”等等......当 FIELD_NAME 是“EMPLOYEE_ID”时,FIELD_VALUE 数据是 102、104 和所有数值。在甲骨文它工作正常。它只发生在 SQL SERVER
  • @DenisRubashkin 不同的客户可能有不同版本的 SQL SERVER。不确定是什么版本。在这里,我使用的是 SQL SERVER 2012
  • 已解决。为了让 SQL SERVER 使用正确的连接顺序,我们必须使用“OPTION (FORCE ORDER)”

标签: sql-server query-optimization sql-execution-plan


【解决方案1】:

如果您使用的是 SQL Server 2012 或更高版本,请尝试以下操作

SELECT FIELD_VALUE,
  FREQUENCY_COUNT
FROM Table1 IFNV
INNER JOIN Table2 IFV
ON IFNV.FIELD_KEY = IFV.FIELD_KEY
INNER JOIN Table3 IFVSD
ON IFVSD.FUNCTION_KEY       = IFNV.FUNCTION_KEY
WHERE IFVSD.PROFILE_RUN_KEY = 78
AND IFV.FIELD_NAME          = 'EMPLOYEE_ID'
AND
  CASE
    WHEN IFV.IS_VIRTUAL = 0
    THEN IFV.RECORD_NAME
    ELSE IFNV.RULE_NAME
  END = 'EMPLOYEES'
  AND FIELD_VALUE IS NOT NULL
ORDER BY FREQUENCY_COUNT DESC,
         TRY_CAST(FIELD_VALUE AS NUMERIC(6,0)) DESC;

如果您使用的是早于 2012 的 SQL Server 版本,请尝试以下操作。

SELECT FIELD_VALUE,
  FREQUENCY_COUNT
FROM Table1 IFNV
INNER JOIN Table2 IFV
ON IFNV.FIELD_KEY = IFV.FIELD_KEY
INNER JOIN Table3 IFVSD
ON IFVSD.FUNCTION_KEY       = IFNV.FUNCTION_KEY
WHERE IFVSD.PROFILE_RUN_KEY = 78
AND IFV.FIELD_NAME          = 'EMPLOYEE_ID'
AND
  CASE
    WHEN IFV.IS_VIRTUAL = 0
    THEN IFV.RECORD_NAME
    ELSE IFNV.RULE_NAME
  END = 'EMPLOYEES'
  AND FIELD_VALUE IS NOT NULL
ORDER BY FREQUENCY_COUNT DESC,
         CASE   WHEN FIELD_VALUE NOT LIKE '%[^0-9]%'
                THEN CAST(FIELD_VALUE AS NUMERIC(6,0))
                ELSE NULL 
         END DESC;

编辑

基本上这意味着您正在尝试将一个值转换为大于 numeric(6,0) 的 numeric(6,0) 。一个更简单的选择是在 order by 子句中使用 LEFT(FIELD_VALUE , 6) 而不是使用 CAST

SELECT FIELD_VALUE,
  FREQUENCY_COUNT
FROM Table1 IFNV
INNER JOIN Table2 IFV
ON IFNV.FIELD_KEY = IFV.FIELD_KEY
INNER JOIN Table3 IFVSD
ON IFVSD.FUNCTION_KEY       = IFNV.FUNCTION_KEY
WHERE IFVSD.PROFILE_RUN_KEY = 78
AND IFV.FIELD_NAME          = 'EMPLOYEE_ID'
AND
  CASE
    WHEN IFV.IS_VIRTUAL = 0
    THEN IFV.RECORD_NAME
    ELSE IFNV.RULE_NAME
  END = 'EMPLOYEES'
  AND FIELD_VALUE IS NOT NULL
ORDER BY FREQUENCY_COUNT DESC,
         LEFT(FIELD_VALUE , 6) DESC;

【讨论】:

  • 您好,感谢您的建议。这个我已经试过了。这部分的问题是 IsNumeric 部分本身未能给出错误“将 nvarchar 转换为数据类型数字的算术溢出错误”。这就是我们在铸造过程中增加精度和比例的原因
  • 主要问题是 SQL SERVER 中的查询在强制转换操作期间考虑了所有列(即使它不是数字)
  • @harendrapratapsingh 现在尝试我使用 NOT LIKE 运算符而不是 Isnumeric 运算符,ISNUMERIC 无论如何都非常没用,它还将像 123a1 这样的值解释为数值。
  • 与之前相同的错误。我附上截图
  • 添加截图
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 2011-04-12
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多