Ich aktualisiere derzeit ein Legacy-System, mit dem Benutzer einen Teil des Schemas einer seiner Tabellen diktieren können. Benutzer können über diese Schnittstelle Spalten aus der Tabelle erstellen und entfernen. Dieses Legacy-System verwendet ADO 2.8 und verwendet SQL Server 2005 als Datenbank (Sie wollen nicht einmal wissen, welche Datenbank es verwendet hat, bevor der Versuch, dieses Biest zu modernisieren, begonnen hat ... aber ich schweife ab.)Update Schema und Zeilen in einer Transaktion, SQL Server 2005
Im selben Bearbeitungsprozess können Benutzer eine Liste gültiger Werte definieren (und ändern), die in diesen benutzererstellten Feldern gespeichert werden können (wenn der Benutzer einschränken möchte, was sich in dem Feld befinden kann).
Wenn der Benutzer die Liste der gültigen Einträge für ein Feld ändert, wenn er einen gültigen Wert entfernt, kann er einen neuen "gültigen Wert" auswählen, um alle Zeilen mit diesem (jetzt ungültigen) Wert zuzuordnen es, damit sie jetzt wieder einen gültigen Wert haben. Beim Durchsehen des alten Codes habe ich gemerkt, dass es extrem anfällig dafür ist, das System in einen ungültigen Zustand zu versetzen, weil die oben erwähnten Änderungen nicht innerhalb einer Transaktion ausgeführt werden (wenn also jemand anders auf halbem Weg durch den erwähnten Prozess kam) oben und machte ihre eigenen Änderungen ... nun, Sie können sich vorstellen, die Probleme, die verursachen könnten).
Das Problem ist, ich habe versucht, sie unter einer einzigen Transaktion zu aktualisieren, aber immer wenn der Code zu dem Teil kommt, wo es das Schema dieser Tabelle ändert, alle anderen Änderungen (Aktualisieren von Werten in Zeilen , sei es in der Tabelle, wo sich das Schema geändert hat oder nicht ... sie können völlig unabhängige Tabellen sein, die bis zu diesem Punkt in der Transaktion gemacht wurden, scheinen stillschweigend fallengelassen zu werden. Ich erhalte keine Fehlermeldung, die besagt, dass sie gelöscht wurden, und wenn ich die Transaktion am Ende festschreibe, wird kein Fehler ausgelöst ... aber wenn ich in die Tabellen schaue, die in der Transaktion aktualisiert werden sollen, nur die neuen Spalten gibt es. Keine der vorgenommenen Nicht-Schema-Änderungen wird gespeichert.
Im Netz nach Antworten zu suchen hat sich bis jetzt als eine Verschwendung von ein paar Stunden erwiesen ... also wende ich mich hier um Hilfe. Hat jemand jemals versucht, eine Transaktion über ADO durchzuführen, die sowohl das Schema einer Tabelle aktualisiert als auch Zeilen in Tabellen aktualisiert (sei es dieselbe Tabelle oder andere)? Ist es nicht erlaubt? Gibt es Unterlagen, die in dieser Situation hilfreich sein könnten?
EDIT:
Okay, ich habe eine Spur, und diese Befehle wurden in die Datenbank (Erläuterungen in Klammern) gesendet
(ich weiß nicht, was hier geschieht, sieht aus wie es ist ein zu schaffen Temporär gespeicherte Prozedur ...?)
declare @p1
int set @p1=180150003 declare @p3 int
set @p3=2 declare @p4 int set @p4=4
declare @p5 int set @p5=-1
(retreiving die Tabelle, die hier hält, Definitionsinformationen für die Benutzer-generierte Felder)
exec sp_cursoropen @p1 output,N'SELECT * FROM CustomFieldDefs ORDER BY Sequence',@p3 output,@p4 output,@p5 output select @p1, @p3, @p4, @p5
go
(Ich glaube, mein Code wurde Iterieren durch die Liste von ihnen greifen die aktuelle Informationen)
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursorfetch 180150003,1025,1,1
go
exec sp_cursorfetch 180150003,1028,1,1
go
exec sp_cursorfetch 180150003,32,1,1
go
(Dies scheint zu sein, wo ich die geänderten Daten für die Definitionen bin Eingabe, gehe ich durch jeden und alle Änderungen aktualisieren, die in den Definitionen aufgetreten für die Sitte selbst Felder)
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=1,@Description='asdf',@Format='U|',@IsLookUp=1,@Length=50,@Properties='U|',@Required=1,@Title='__asdf',@Type='',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=2,@Description='give',@Format='Y',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_give',@Type='B',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=3,@Description='up',@Format='###-##-####',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_up',@Type='N',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=4,@Description='Testy',@Format='',@IsLookUp=0,@Length=50,@Properties='',@Required=0,@Title='_Testy',@Type='',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=5,@Description='you',@Format='U|',@IsLookUp=0,@Length=250,@Properties='U|',@Required=0,@Title='_you',@Type='',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=6,@Description='never',@Format='mm/dd/yyyy',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_never',@Type='D',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=7,@Description='gonna',@Format='###-###-####',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_gonna',@Type='C',@_Version=1
go
exec sp_cursorfetch 180150003,32,1,1
go
(Dies ist, wo meine Code entfernt die durch die Schnittstelle gelöscht, bevor diese Einsparung] begann ... es ist auch das einzige, was, soweit ich das passiert eigentlich während dieser Transaktion sagen kann)
ALTER TABLE CustomizableTable DROP COLUMN _weveknown;
(Nun, wenn eine der Definitionen wurden so verändert, dass die Verwendung Die Eigenschaften von r-created-Spalten müssen geändert werden oder Indizes für die Spalten müssen hinzugefügt/entfernt werden. Dies wird hier gemacht, zusammen mit einem Standardwert für alle Zeilen, die noch keinen Wert für die angegebene Spalte haben ... beachten Sie, dass, soweit ich das beurteilen kann, nichts von alldem tatsächlich passiert, wenn die gespeicherte Prozedur beendet ist.)
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '__asdf'
go
ALTER TABLE CustomizableTable ALTER COLUMN __asdf VarChar(50) NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx___asdf') CREATE NONCLUSTERED INDEX idx___asdf ON CustomizableTable (
__asdf ASC) WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF);
go
select * from IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx___asdf') CREATE NONCLUSTERED INDEX idx___asdf ON
CustomizableTable (__asdf ASC) WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF);
go
UPDATE CustomizableTable SET [__asdf] = '' WHERE [__asdf] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_give'
go
ALTER TABLE CustomizableTable ALTER COLUMN _give Bit NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__give') DROP INDEX idx__give ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_give] = 0 WHERE [_give] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_up'
go
ALTER TABLE CustomizableTable ALTER COLUMN _up Int NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__up') DROP INDEX idx__up ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_up] = 0 WHERE [_up] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_Testy'
go
ALTER TABLE CustomizableTable ADD _Testy VarChar(50) NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__Testy') DROP INDEX idx__Testy ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_Testy] = '' WHERE [_Testy] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_you'
go
ALTER TABLE CustomizableTable ALTER COLUMN _you VarChar(250) NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__you') DROP INDEX idx__you ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_you] = '' WHERE [_you] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_never'
go
ALTER TABLE CustomizableTable ALTER COLUMN _never DateTime NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__never') DROP INDEX idx__never ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_never] = '1/1/1900' WHERE [_never] IS NULL
go
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_gonna'
go
ALTER TABLE CustomizableTable ALTER COLUMN _gonna Money NULL
go
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__gonna') DROP INDEX idx__gonna ON CustomizableTable WITH (ONLINE = OFF);
go
UPDATE CustomizableTable SET [_gonna] = 0 WHERE [_gonna] IS NULL
go
(Abschluss der Transaktion ...?)
exec sp_cursorclose 180150003
go
Nach all dieser Anzeige o oben erfolgt nur das Löschen der Spalte. Alles davor und danach in der Transaktion scheint ignoriert zu werden, und es gab keine Nachrichten in der SQL-Ablaufverfolgung, um anzuzeigen, dass während der Transaktion etwas schief gelaufen ist.
Aye, ich habe in der Dokumentation gelesen, dass ich keinen clientseitigen Cursor verwenden kann, um Transaktionen durchzuführen, und ich habe auch sichergestellt, dass sie das sind alle mit der gleichen aktiven Verbindung auch. Vielen Dank für die Hilfe mit diesem, es war ein seltsames Problem sicher = ( – EdgarVerona
) Gute Infos zu den gespeicherten Prozeduren dort ... Ich hatte das Gefühl, dass es so etwas tat , aber ich war mir nicht sicher ... Ich hatte noch nie einen Trace vor heute gemacht, also habe ich nie gesehen, dass solche Prozeduren unter der Haube aufgerufen werden. =) =) – EdgarVerona
Keine Sorge, du hast das Beste ausprobiert Könnte mit den Informationen angegeben werden. Ich kratze meinen Kopf darauf gut ... Aye, ich benutze Recordset.Update jetzt für die tatsächlichen Zeile Updates, wie Sie sagten ... Ich werde versuchen, mit einer direkt generierten Update-Anweisung statt und sehen, wie das funktioniert . – EdgarVerona