sql-server - BEGIN TRY and EXECUTE 动态简单查询错误
问题描述
当我执行附加查询时出现错误:
消息 0,级别 11,状态 0,行 0 当前命令发生严重错误。结果,如果有的话,应该丢弃。
当 try-catch 被注释时,它会起作用,在使用其他列时也是如此。当 partition by 被删除时,它也可以工作。
有人可以说这里的错误根源在哪里还是一些 sql server 错误?
询问:
BEGIN TRY
DECLARE @vSqlCmd NVARCHAR(MAX) = N'
SELECT TOP 1 V = d.collation_name, C = COUNT(1) OVER (PARTITION BY d.collation_name)
FROM sys.all_columns d;';
SELECT @vSqlCmd;
EXECUTE (@vSqlCmd);
END TRY
BEGIN CATCH
PRINT 'CATCH!!!';
THROW;
END CATCH
解决方案
这是一个错误。我已经在这里报告了
目前尚不清楚您为什么需要此查询,下面解释了该问题以及如果有一些合理的理由需要此查询,如何避免它。
以下查询返回两个 object_id-103085222
和-593
SELECT object_id ,name
FROM sys.system_columns
where system_type_id in (35,99,167,175,231,239) and collation_name IS NULL
这些与以下对象有关
+------------+----------------------------------+
| id | name |
+------------+----------------------------------+
| -103085222 | pdw_nodes_pdw_physical_databases |
| -593 | pdw_table_mappings |
+------------+----------------------------------+
由于某种原因,这两个都有一个字符串列(称为physical_name
),SQL Server 无法解析其排序规则。由于这些对象仅与并行数据仓库相关,甚至在产品的其他版本中都不存在,这通常不是问题。
sys.all_columns
引用sys.system_columns
使用以下表达式的视图collation_name
:convert(sysname, ColumnPropertyEx(object_id, name, 'collation'))
重现该问题的更简单案例是
BEGIN TRY
SELECT columnpropertyex(-593, 'physical_name', 'collation')
END TRY
BEGIN CATCH
END CATCH
或者
SET XACT_ABORT ON;
SELECT columnpropertyex(-593, 'physical_name', 'collation')
两者都返回
消息 0,级别 11,状态 0,第 33 行
当前命令发生严重错误。结果,如果有的话,应该丢弃。
在TRY
块外运行时返回NULL
(XACT_ABORT
关闭时)。在幕后,它抛出一个内部处理的异常,最终用户不知道。抛出异常时的调用堆栈显示该GetColumnCollate
函数最终使用 Algebrizer 尝试解析列,但最终失败CAlgTableMetadata::RaiseBadTableException
(可能是因为某处缺少相关的对象定义)。
当在TRY ... CATCH
上下文中运行或XACT_ABORT ON
出现问题时,应该静默忽略错误并返回的位NULL
。将重复键插入到索引中ignore_dup_key ON
也会引发一个内部错误,该错误被忽略但没有相同的问题。
因此,解决问题的一种方法是将引用包装collation_name
在一个表达式中,这样当在块内运行时CASE
,它永远不会针对这两个问题进行评估。object_id
TRY
BEGIN TRY
DECLARE @vSqlCmd NVARCHAR(MAX) = N'
SELECT TOP 1 V = ca.safe_collation_name, C = COUNT(1) OVER (PARTITION BY ca.safe_collation_name)
FROM sys.all_columns d
CROSS APPLY (SELECT CASE WHEN object_id NOT IN (-593,-103085222) THEN collation_name END) ca(safe_collation_name);
';
SELECT @vSqlCmd;
EXECUTE (@vSqlCmd);
END TRY
BEGIN CATCH
PRINT 'CATCH!!!';
THROW;
END CATCH
这并不能保护您免受将来将有问题的元数据添加到产品中的不同情况。然而,我再次质疑这个查询的必要性。您提供的查询非常奇怪,很难告诉您应该用什么替换它。
推荐阅读
- node.js - 如何在没有模数检查的情况下确保公钥属于私钥(RSA)?
- azure - 无法在 Azure 机密计算 (ACC) 上创建 VM
- java - 在正则表达式中分离突发部分
- python - 如何垂直打印水平列表?更多信息在下面
- fortran - 逐行读取不同变量的文本文件
- html - 将设计表单输入值设置到 div 的右侧
- java - StringBuffer中“buffer”这个词怎么表示同步
- javascript - 如何通过 post 方法和 nodejs 发送多种编码类型?
- java - Android-Studio:如何将地图附加到 NavigationDrawer 片段
- python - 无法按标签删除熊猫数据框中的列