Benutzer mit den meisten Antworten
sp_rename in einer Transaktion

Frage
-
Hallo,
ich stelle Daten in SQL Server Datenbanktabellen zur Verfügung, die regelmäßig aus einer DB2 kopiert werden. Damit es dabei zu keinen Unterbrechungen in der Datenbereitstellung gibt, werden die Daten zunächst in temporäre Tabellen kopiert, bevor die temporären Tabellen mittels sp_rename umbenannt werden. Das funktioniert bislang auch immer (bei den unterschiedlichsten Kunden). Nun gibt es bei einem Kunden aber das Problem, dass die Standard-Warnung von sp_rename zu einem Rollback meiner Transktion führt. Hat hierzu jemand eine Idee?
SQL Server Version ist
Microsoft SQL Server 2014 (SP2-GDR) (KB4019093) - 12.0.5207.0 (X64)
Jul 3 2017 02:25:44
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
Mein Skript sieht wie folgt aus:
-- Beginne eine neue Datenbanktransaktion, so dass während der Ausführung keine
-- Daten gelesen werden können und im Fehlerfall ein Rollback möglich ist.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION ReleaseTable WITH MARK N'RELEASE_DV_PARTNER';
BEGIN TRY
-- Lösche nun die Vorgängertabelle mit älterem Datenbestand.
IF OBJECT_ID('dbo.DV_PARTNER','U') IS NOT NULL
DROP TABLE [dbo].[DV_PARTNER];
-- Ersetze die Vorgängertabelle durch die neu befüllte Zieltabelle.
EXECUTE sp_rename 'TMP_PARTNER', 'DV_PARTNER';
-- Benenne den Primärschlüssel um
ALTER TABLE [dbo].[DV_PARTNER] DROP CONSTRAINT [PK_TMP_PARTNER];
ALTER TABLE [dbo].[DV_PARTNER] ADD CONSTRAINT [PK_DV_PARTNER] PRIMARY KEY CLUSTERED ([ID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [INDEX]
-- Lösche temporäre Tabellen und Sichten
IF OBJECT_ID('dbo.TMP_VERSICHERTEPERSON_FAMILIENVERSICHERTER','U') IS NOT NULL
DROP TABLE [dbo].[TMP_VERSICHERTEPERSON_FAMILIENVERSICHERTER];
IF OBJECT_ID('dbo.TMP_VERSICHERTEPERSON_MITGLIED','U') IS NOT NULL
DROP TABLE [dbo].[TMP_VERSICHERTEPERSON_MITGLIED];
IF OBJECT_ID('dbo.TMP_VERSICHERTEPERSON_STORNIERT','U') IS NOT NULL
DROP TABLE [dbo].[TMP_VERSICHERTEPERSON_STORNIERT];
IF OBJECT_ID('dbo.TMP_VERSICHERTEPERSON','V') IS NOT NULL
DROP VIEW [dbo].[TMP_VERSICHERTEPERSON];
-- Bestätige die Transaktion, falls bis hierher kein Fehler auftrat.
COMMIT TRANSACTION ReleaseTable;
SELECT 0;
END TRY
BEGIN CATCH
-- Stelle die Ursprungssitutation im Fehlerfall wieder her. Die Vorgänger-
-- tabelle mit dem älteren Datenbestand bleibt so erhalten.
ROLLBACK TRANSACTION ReleaseTable;
RAISERROR('Die Tabelle DV_PARTNER konnte nicht freigegeben werden.',16,1);
END CATCHDie Meldung, welche dann auch zum Betreten des CATCH Blocks führt, ist:
Vorsicht: Wenn Sie Teile eines Objektnamens ändern, werden Skripts und gespeicherte Prozeduren möglicherweise funktionsunfähig.
Grüße,
Michael
Antworten
-
Hallo Michael,
die "Fehlermeldung" ist keine wirkliche Fehlermeldung sondern lediglich eine Warnung. Wie kommst Du darauf, dass der Block tatsächlich den CATCH-Block ausführt?
Ich habe - in vereinfachter Form - das ganze mal ausprobiert:
USE CustomerOrders; GO BEGIN TRANSACTION BEGIN TRY EXEC sp_rename @objname = N'dbo.newCustomers', @objtype = N'OBJECT', @newname = N'Customers'; END TRY BEGIN CATCH SELECT 'Voll der Fehler...'; END CATCH; GO COMMIT TRANSACTION; GO
Die Transaktion wird ganz normal beendet. Die "Fehlermeldung" ist message_id 15477. Diese Meldung ist lediglich ein Hinweis, der innerhalb von sp_rename erzeugt wird, um darauf hinzuweisen, dass ein Umbenennen dazu führen kann, dass Prozeduren, Views, etc. das Objekt nicht mehr ansprechen können.
In der Prozedur sp_rename weist Microsoft selbst auf diesen Umstand hin...
"WITH DEFERRED RESOLUTION, sql_dependencies IS NOT VERY ACCURATE, SO WE ALSO RAISE THIS WARNING **UNCONDITIONALLY**, EVEN FOR NON-OBJECT RENAMES"
und generiert den entsprechenden Fehler. Um den Hintergrund zu verstehen, muss man den Aufruf in sp_rename etwas genauer untersuchen:
raiserror(15477,-1,-1)
Hierbei ist vor allen Dingen der zweite Parameter (-1) zu beachten. Mit Hilfe von -1 wird die Meldung mit dem Schweregrad ausgegeben, der in sys.messages für die entsprechende Message_id angeben ist (für 15477 ist das der Wert 10!)
Die von RAISERROR generierten Fehler funktionieren genauso wie Fehler, die vom Code der Datenbank-Engine generiert werden. Die von RAISERROR angegebenen Werte werden von den Systemfunktionen ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY, ERROR_STATE und @@ ERROR gemeldet.
Wenn RAISERROR mit einem Schweregrad von 11 oder höher in einem TRY-Block ausgeführt wird, überträgt es die Steuerung an den zugeordneten CATCH-Block. Der Fehler wird an den Aufrufer zurückgegeben, wenn RAISERROR ausgeführt wird:
Somit sollte der CATCH-Block nicht erreicht werden - zumindest nicht durch sp_rename.
Uwe Ricken (Blog | Twitter)
Microsoft Certiifed Master - SQL Server 2008
Microsoft Certified Solution Master - CHARTER Data Platform
Microsoft Certified Solution Expert - Data Platform
db Berater GmbH
Microsoft SQL Server Blog (german only)- Bearbeitet Uwe RickenMVP Donnerstag, 30. August 2018 16:21
- Als Antwort vorgeschlagen Ivan DragovMicrosoft contingent staff, Moderator Montag, 3. September 2018 05:53
- Als Antwort markiert Ivan DragovMicrosoft contingent staff, Moderator Dienstag, 11. September 2018 11:19
Alle Antworten
-
Du kannst es damit versuchen:
https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-warnings-transact-sql?view=sql-server-2017
Den Status kannst du aktuell per Select abfragen, die Warnings ggf. abschalten, die Aktion ausfhren und die Warnings ggf. wieder einschalten.
In der Doku finde ich nichts auf die Schnelle, ob das sitzungsspezifisch oder sogar transaktionsspezifisch ist, also nach Disconnect oder Commit/Rollback zurückgesetzt wird.- Bearbeitet Der Suchende Mittwoch, 29. August 2018 16:13
-
Am 29.08.2018 schrieb sp_rename in einer Transaktion ausführen:
Microsoft SQL Server 2014 (SP2-GDR) (KB4019093) - 12.0.5207.0 (X64)
Jul 3 2017 02:25:44Dein SQL Server ist nicht mehr aktuell, du solltest das letzte CU
installieren. Details zu den Builds gibt es hier:
https://buildnumbers.wordpress.com/sqlserver/Servus
Winfried
WSUS Package Publisher: http://wsuspackagepublisher.codeplex.com/
HowTos zum WSUS Package Publisher http://www.wsus.de/wpp
GPO's: http://www.gruppenrichtlinien.de
NNTP-Bridge für MS-Foren: http://communitybridge.codeplex.com/
GP-PACK - PRIVACY AND TELEMETRIE: http://www.gp-pack.com/ -
Ich habe hier eine Diskussion gefunden, dass man dies nicht ausschalten kann:
https://social.technet.microsoft.com/Forums/sqlserver/en-US/bb121a87-2681-4a9f-b38a-6870657c95e4/sprename-suppress-warning-message?forum=transactsqlWofür die Routine dann gut ist, entzieht sich mir.
https://docs.microsoft.com/de-de/sql/relational-databases/system-stored-procedures/sp-rename-transact-sql?view=sql-server-2017Auf die Problem wird hingewiesen, allerdings entzieht sich mir, wie ich dann die Routine anwenden soll.
Umgekehrt könnte es ja auch sein, dass man speziell bei diesem Warning trotzdem einen Commit machen kann um die Umbenennung wirksam werden zu lassen.Mittels Error_Message() kannst du ja darauf prüfen:
https://docs.microsoft.com/de-de/sql/t-sql/functions/error-message-transact-sql?view=sql-server-2017Alternativ kannst du ja auch direkt den Rename verwenden (Version?):
https://docs.microsoft.com/de-de/sql/t-sql/statements/rename-transact-sql?view=aps-pdw-2016-au7 -
Hallo Michael,
die "Fehlermeldung" ist keine wirkliche Fehlermeldung sondern lediglich eine Warnung. Wie kommst Du darauf, dass der Block tatsächlich den CATCH-Block ausführt?
Ich habe - in vereinfachter Form - das ganze mal ausprobiert:
USE CustomerOrders; GO BEGIN TRANSACTION BEGIN TRY EXEC sp_rename @objname = N'dbo.newCustomers', @objtype = N'OBJECT', @newname = N'Customers'; END TRY BEGIN CATCH SELECT 'Voll der Fehler...'; END CATCH; GO COMMIT TRANSACTION; GO
Die Transaktion wird ganz normal beendet. Die "Fehlermeldung" ist message_id 15477. Diese Meldung ist lediglich ein Hinweis, der innerhalb von sp_rename erzeugt wird, um darauf hinzuweisen, dass ein Umbenennen dazu führen kann, dass Prozeduren, Views, etc. das Objekt nicht mehr ansprechen können.
In der Prozedur sp_rename weist Microsoft selbst auf diesen Umstand hin...
"WITH DEFERRED RESOLUTION, sql_dependencies IS NOT VERY ACCURATE, SO WE ALSO RAISE THIS WARNING **UNCONDITIONALLY**, EVEN FOR NON-OBJECT RENAMES"
und generiert den entsprechenden Fehler. Um den Hintergrund zu verstehen, muss man den Aufruf in sp_rename etwas genauer untersuchen:
raiserror(15477,-1,-1)
Hierbei ist vor allen Dingen der zweite Parameter (-1) zu beachten. Mit Hilfe von -1 wird die Meldung mit dem Schweregrad ausgegeben, der in sys.messages für die entsprechende Message_id angeben ist (für 15477 ist das der Wert 10!)
Die von RAISERROR generierten Fehler funktionieren genauso wie Fehler, die vom Code der Datenbank-Engine generiert werden. Die von RAISERROR angegebenen Werte werden von den Systemfunktionen ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY, ERROR_STATE und @@ ERROR gemeldet.
Wenn RAISERROR mit einem Schweregrad von 11 oder höher in einem TRY-Block ausgeführt wird, überträgt es die Steuerung an den zugeordneten CATCH-Block. Der Fehler wird an den Aufrufer zurückgegeben, wenn RAISERROR ausgeführt wird:
Somit sollte der CATCH-Block nicht erreicht werden - zumindest nicht durch sp_rename.
Uwe Ricken (Blog | Twitter)
Microsoft Certiifed Master - SQL Server 2008
Microsoft Certified Solution Master - CHARTER Data Platform
Microsoft Certified Solution Expert - Data Platform
db Berater GmbH
Microsoft SQL Server Blog (german only)- Bearbeitet Uwe RickenMVP Donnerstag, 30. August 2018 16:21
- Als Antwort vorgeschlagen Ivan DragovMicrosoft contingent staff, Moderator Montag, 3. September 2018 05:53
- Als Antwort markiert Ivan DragovMicrosoft contingent staff, Moderator Dienstag, 11. September 2018 11:19
-
Hallo Uwe,
wie ich darauf komme, dass der CATCH Block angesprungen wird? Ganz einfach, ich erhalte diese Meldung, die nur von "meinem" CATCH Block ausgegeben wird:
Vorsicht: Wenn Sie Teile eines Objektnamens ändern, werden Skripts und gespeicherte Prozeduren möglicherweise funktionsunfähig.
Meldung 50000, Ebene 16, Status 1, Zeile 31
Die Tabelle DV_PARTNER konnte nicht freigegeben werden.Üblicherweise wird der auch bei der Warnung 15477 nicht angesprungen, nur bei einem SQL Server System eines Kunden ist das nun mal so. Da ich schon gefühlt zehn verschiedene SQL Server Versionen ohne Probleme genutzt habe, vermute ich bestimmte System- oder Kontoeinstellungen auf dem SQL Server, die das Verhalten zu verantworten haben.
BG Michael
-
Hallo zusammen,
die Datenbank wurde vom Kunden mit dem Wiederherstellungsmodell "Vollständig" angelegt, statt "Einfach", wie von mir erwartet. Demnach und weil die Dateigruppe PRIMARY von der Größe beschränkt ist, wurde tatsächlich wegen der Neuerstellung des PRIMARY KEY ein Fehler ausgelöst, nicht etwa durch die Warnung aus sp_rename. Uwe hat also vollkommen recht, das war überhaupt nicht der Grund.
Sinnvoller als
-- Benenne den Primärschlüssel um
ALTER TABLE [dbo].[DV_PARTNER] DROP CONSTRAINT [PK_TMP_PARTNER];
ALTER TABLE [dbo].[DV_PARTNER] ADD CONSTRAINT [PK_DV_PARTNER] PRIMARY KEY CLUSTERED ([ID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [INDEX]ist ohnehin
-- Benenne den Primärschlüssel um
EXECUTE sp_rename N'TMP_PARTNER.PK_TMP_PARTNER', N'PK_DV_PARTNER', N'INDEX';Danke an alle und schönes Wochenende.
Michael
- Als Antwort vorgeschlagen Michael Petöfalvi Freitag, 7. September 2018 14:37