НАЧАТЬ ИСПОЛНИТЬ и ВЫПОЛНИТЬ dynamici c простая ошибка запроса - PullRequest
1 голос
/ 18 февраля 2020

при выполнении вложенного запроса я получаю сообщение об ошибке:

Сообщение 0, уровень 11, состояние 0, строка 0 Произошла серьезная ошибка в текущей команде. Результаты, если таковые имеются, должны быть отброшены.

Когда комментируется try-catch, он работает так же, когда используется другой столбец. Когда раздел по удален, он также работает.

Может кто-нибудь сказать, где здесь root ошибка или какая-то sql ошибка сервера?

Запрос:

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

1 Ответ

1 голос
/ 18 февраля 2020

Это ошибка. Я сообщил об этом здесь

Непонятно, зачем вам этот запрос, ниже объясняется проблема и как ее избежать, если для этого запроса есть какая-то разумная причина.

Следующий запрос возвращает два object_ids -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 Сервер не может разрешить сопоставление для. Поскольку эти объекты относятся только к Parallel Data Warehouse и даже не существуют должным образом в других версиях продукта, обычно это не проблема.

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')

Оба возвращают

Msg 0, уровень 11, состояние 0, строка 33

Произошла серьезная ошибка в текущей команде. Результаты, если таковые имеются, должны быть отброшены.

При запуске вне блока TRY возвращается NULL (когда XACT_ABORT выключено). За кулисами создается исключение, которое обрабатывается внутри, и конечный пользователь не знает об этом. Стек вызовов, когда генерируется исключение, показывает, что функция GetColumnCollate заканчивается использованием Algebrizer, чтобы попытаться разрешить столбец, и в конечном итоге происходит сбой в CAlgTableMetadata::RaiseBadTableException (возможно, где-то отсутствует определение связанного объекта).

enter image description here

При запуске в контексте TRY ... CATCH или с XACT_ABORT ON что-то не так с битом, который должен игнорировать ошибку и возвращать NULL. Вставка дубликата ключа в индекс с ignore_dup_key ON также вызывает внутреннюю ошибку, которая игнорируется, но не имеет той же проблемы.

Таким образом, один из способов решения проблемы - заключить ссылку на collation_name в выражение CASE, чтобы он никогда не оценивался для этих двух проблемных c 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

Это не защитит вас от различных проблемных метаданных c, добавляемых в продукт в будущем. Снова я подвергаю сомнению необходимость этого запроса как бы то ни было. Заданный вами запрос настолько странен, что трудно посоветовать, чем его заменить.

...