Frage

Wenn Sie die Spalte einer Tabelle als eine berechnete Spalte einrichten, deren Formel eine Funktion aufruft, wird es zu einem Schmerz, diese zugrunde liegende Funktion zu ändern. Bei jeder Änderung müssen Sie jede einzelne Spalte finden, deren Formel, die die Funktion verweist, die Referenz entfernen, die Tabelle speichern, die Funktion ändern, alles zurück hinzufügen und erneut speichern. Sogar kleine Veränderungen sind Albträume.

Können Sie SQL Server sagen, dass Sie egal sind, dass die Funktion von Formeln verwiesen wird und einfach die zugrunde liegende Funktion ändern wird?

Zusätzliche Details: Die berechnete Spalte wird nicht durch eine FK-Einschränkung bestehen oder verwiesen, da sie nicht deterministisch ist. Die Funktion berücksichtigt die aktuelle Zeit. Es geht um die Frage, ob ein Datensatz abgelaufen ist oder nicht.

War es hilfreich?

Lösung

Nein, soweit ich weiß, können Sie dies nicht tun - Sie müssen zuerst alle berechneten Spalten entfernen, die auf eine Funktion verweisen, die Funktion ändern und dann die berechneten Spalten neu erstellen.

Vielleicht gibt uns MS einen Befehl "Funktion für Erstellen oder Alter" in SQL Server 2010/2011? :-)

Marc

Andere Tipps

Die Folgen des Alters könnten riesig sein.

Haben Sie die Spalten indiziert? Benutzt es in einer Aussicht mit Schemabinding? Behielt es an? Ausländische Schlüsselbeziehung dazu?

Was ist, wenn die Änderung den Datentyp, die Nullabilität oder den Determinismus ändert?

Es ist einfacher, die Änderung der Funktion mit Abhängigkeiten zu stoppen, als mit so vielen Szenarien umzugehen.

Entschuldigung für diese späte Antwort, aber es kann nützlich sein.

Sie können eine Dummy -Funktion für jede berechnete Spalte verwenden, die Ihre reale Funktion aufruft.

Beispiel:
Die Computerspalte Verwendet die Formel: dbo.link_comp ('123')
Diese Funktion leiten Sie die Argumente und Aufrufe weiter und geben Sie die Funktion dbo.link ('123') (Ihre reale Funktion) zurück)
Beide Funktionen müssen nur dieselben Argumente verwenden und denselben Typ zurückgeben.

Dann ist die gesperrte Funktion dbo.link_comp und Sie können immer noch dbo.link verändern.
Wenn Ihre Funktion von einem anderen SQL aufgerufen wird, können Sie auch Ihren realen Funktionsnamen dbo.link verwenden. Die Dummy -Funktion dbo.link_comp ist nur für die Computerspalte geeignet.

Nehmen Sie Tabelle T1 mit den Spalten C1, C2, C3, C4, C5 an, wobei C4 eine Computerspalte ist

Nehmen Sie auch die Funktion der C4 -Referenzen an, die Sie durch Newfunc ersetzt werden möchten

Bewegen Sie zunächst nicht berechnete Spalten von allen Zeilen in eine Temp-Tabelle

Select C1, C2, C3, C5 into TmpT1 from T1
Go

Löschen Sie als nächstes alle Zeilen von T1

Delete From T1
go

Jetzt können Sie Spalte C4 ändern

Alter table T1 alter column C4 as dbo.NewFunc()
Go

Nehmen Sie nun die gespeicherten Daten in die ursprüngliche Tabelle zurück

Insert Into T1 (C1,C2,C3,C5) select C1,C2,C3,C5 from TmpT1

Löschen Sie nun die Temperaturtabelle

Drop Table TmpT1

Sie könnten es mit einem guten Schema -Vergleichen versuchen, das das Skript für Sie erstellt :)

Sie können die Spalte ändern, die nicht kompetiert werden soll, und sie per Trigger aktualisieren.

Oder Sie können die Tabelle in etwas anderes umbenennen, die berechnete Spalte fallen lassen und eine Ansicht anstelle der ursprünglichen Tabelle (dh mit dem ursprünglichen Tabellennamen) und der "berechneten" Spalte, die Sie benötigen, einbeziehen.

Bearbeiten: Beachten Sie, dass dies mit Ihren Einfügen in den ursprünglichen Tabellennamen (jetzt eine Ansicht) durcheinander gebracht wird. Offensichtlich können Sie die alte Tabelle behalten, die berechnete Spalte fallen lassen und eine separate Ansicht erstellen, die die Computerspalte enthielt.

Wir mussten genug Zeiten mit berechneten Spalten zusammenarbeiten, um entschieden zu haben, dass sie mehr Ärger haben als sie gewinnen. Fail-SAF-Einsätze (1), versuchen Sie, in Tabellen mit berechneten Spalten in Ansichten einzulegen, Dinge, die mit festgelegten Aritabort durcheinander bringen müssen.

(1) Wir haben fehlsichere Einsätze wie:

Einfügen in mytable select * von myothertable wo ...

die so konzipiert sind, dass eine neue Spalte eine Tabelle und nicht die andere hinzugefügt wird. Bei der Computerspalte müssen wir alle Spalten explizit benennen, was uns dieses Sicherheitsnetz verliert.

Ich weiß, dass dies zu spät zur Party ist, aber ich hatte heute das gleiche Problem und fand nichts, was das Problem tatsächlich löst, sodass ich schnell eines herausgeschrieben habe.

Im Wesentlichen wird eine temporäre Tabelle erstellt, die die Spalteninformationen für jede berechnete Spalte mithilfe der Funktion enthält und die Spalten aus den Tabellen fällt. Sie aktualisieren dann Ihre Funktion und lassen sie alle Spalten wieder mit ihren Definitionen neu erstellen.

Wenn Sie Änderungen an den Parametern in den Definitionen vornehmen müssen (wie ich es nötig sein muss), können Sie einfach ein Skript angeben, an dem die Definitionen wieder erstellt werden.

Wenn Sie Spalten innerhalb von Indizes oder anderen Anforderungen berechnet haben, können Sie den Code problemlos erweitern, dies ging jedoch über den Umfang meiner Anforderungen hinaus.

Hoffe es kann für jemand anderen nützlich sein.

/* Create temporary table to hold definitions */
CREATE TABLE [#FUNCTION]
(
    [TABLE_NAME] nvarchar(255) NOT NULL,
    [COLUMN_NAME] nvarchar(255) NOT NULL,
    [DEFINITION] nvarchar(255) NOT NULL
)
GO

/* Add data to temp table */
INSERT INTO [#FUNCTION] ( [TABLE_NAME], [COLUMN_NAME], [DEFINITION] )
SELECT TABLE_NAME, COLUMN_NAME, definition FROM INFORMATION_SCHEMA.COLUMNS
INNER JOIN sys.computed_columns ON ( object_id = object_id( TABLE_NAME ) AND name = COLUMN_NAME )
WHERE definition LIKE '%MyFunctionName%'
GO

/* Remove columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] DROP COLUMN [' + @COLUMN_NAME + ']' )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Update function */
-- Update function here
GO

/* Recreate computed columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)
DECLARE @DEFINITION nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME], [DEFINITION] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] ADD [' + @COLUMN_NAME + '] AS ' + @DEFINITION )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Remove temp table */
DROP TABLE [#FUNCTION]
GO
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top