Я пытаюсь реализовать 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.
Что мне делать, чтобы перехватывать исключения с помощью настраиваемых сообщений?
Вы, конечно, не можете использовать такой код (если он работает) для общих целей. Вы ловите каждую ошибку, а затем пытаетесь сгенерировать конкретную, которая может быть совершенно не связана с обнаруженной вами ошибкой. Похоже на проблема XY. И если вы собираетесь использовать терминаторы операторов — а вы должны — вы должны использовать их последовательно для каждого оператора.
преобразовать этот оператор 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;
Примечание:
timestamp
является устаревшим синонимомrowversion
; вам больше не следует использоватьtimestamp
.