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