Перехватывайте исключения с помощью пользовательских сообщений через BEGIN CATCH в TSQL

Я пытаюсь реализовать T-SQL try catch в студии управления SQL Server. Вот мой код:

BEGIN
BEGIN TRY
 alter table [SalesLT].[ProductModel]
 add testtimestamp123 timestamp 
END TRY
BEGIN CATCH
    RAISERROR('MY CUSTOMIZED ERROR MESSAGE',16,1)
END CATCH
END;

Я ожидаю, что я получу свое пользовательское сообщение, если запущу этот код в студии управления сервером sql (потому что у меня есть столбец с типом данных метки времени в этой таблице), но я получаю это сообщение: A table can only have one timestamp column. Because table 'ProductModel' already has one, the column 'testtimestamp123' cannot be added.

Что мне делать, чтобы перехватывать исключения с помощью настраиваемых сообщений?

Примечание: timestamp является устаревшим синонимом rowversion; вам больше не следует использовать timestamp.

Larnu 05.05.2022 16:56

Вы, конечно, не можете использовать такой код (если он работает) для общих целей. Вы ловите каждую ошибку, а затем пытаетесь сгенерировать конкретную, которая может быть совершенно не связана с обнаруженной вами ошибкой. Похоже на проблема XY. И если вы собираетесь использовать терминаторы операторов — а вы должны — вы должны использовать их последовательно для каждого оператора.

SMor 05.05.2022 19:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
31
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

преобразовать этот оператор sql в динамический SQL, тогда ошибка будет выдана в момент выполнения, а не при анализе. Например. что-то вроде этого

DECLARE @sql nvarchar(max) = 'alter table demo add testtimestamp123 timestamp ';
BEGIN TRY
    EXEC sp_executesql @sql 
END TRY
BEGIN CATCH
    RAISERROR('MY CUSTOMIZED ERROR MESSAGE',16,1)
END CATCH

Не все исключения в T-SQL можно «отловить». Это одна из них.

Если вы не хотите использовать «динамический» оператор, вы можете использовать EXISTS против sys объектов, а затем вы можете THROW свою пользовательскую ошибку, если столбец уже существует:

CREATE TABLE dbo.SomeTable (Id int,
                            rowversion rowversion); --Don't use timestamp, it's deprecated

GO
IF NOT EXISTS (SELECT 1
               FROM sys.schemas s
                    JOIN sys.tables t ON s.schema_id = t.schema_id
                    JOIN sys.columns c ON t.object_id = c.object_id
               WHERE s.name = N'dbo'
                 AND t.name = N'SomeTable'
                 AND c.name = N'rowversion')
    ALTER TABLE dbo.SomeTable ADD rowversion rowversion;
ELSE
    THROW 65762, N'A column of the name you want to create already exists. I can''t do this. Sorry :(', 10;

GO
DROP TABLE dbo.SomeTable;

Другие вопросы по теме