Это ошибка. Я сообщил об этом здесь
Непонятно, зачем вам нужен этот запрос, ниже объясняется проблема и как ее избежать, если есть какая-то разумная причина для необходимости этого запроса.
Следующий запрос возвращает два 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 не может разрешить сопоставление. Поскольку эти объекты относятся только к 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
Or
SET XACT_ABORT ON;
SELECT columnpropertyex(-593, 'physical_name', 'collation')
Оба возвращаются
Сообщение 0, уровень 11, состояние 0, строка 33
В текущей команде произошла серьезная ошибка. Результаты, если таковые имеются, должны быть отброшены.
При запуске за пределами блока TRY
возвращается NULL
(когда XACT_ABORT
отключено). За кулисами он выдает исключение, которое обрабатывается внутри, и конечный пользователь не знает об этом. Стек вызовов при возникновении исключения показывает, что функция GetColumnCollate
в конечном итоге использует алгебраизатор для попытки разрешить столбец, и в конечном итоге она терпит неудачу в 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
Это не защищает вас от различных случаев добавления проблемных метаданных в продукт в будущем. Однако я снова сомневаюсь в необходимости этого запроса. Предоставленный вами запрос настолько странный, что трудно посоветовать, чем его заменить.
person
Martin Smith
schedule
18.02.2020