ALTER TABLE con valore DEFAULT costante determinato programmaticamente
-
20-08-2019 - |
Domanda
Sto cercando di aggiungere una colonna (MSSQL 2005) a una tabella (Employee) con un vincolo predefinito di una chiave primaria di un'altra tabella (Dipartimento). Quindi ho intenzione di rendere questa colonna un FK per quella tabella. In sostanza, questo assegnerà i nuovi dipendenti a un dipartimento di base basato sul nome del dipartimento se non viene fornito nessun ID reparto.
Questo non funziona:
DECLARE @ErrorVar INT
DECLARE @DepartmentID INT
SELECT @DepartmentID = DepartmentID
FROM Department
WHERE RealName = 'RocketScience'
ALTER TABLE [Employee]
ADD [DepartmentID] INT NULL
CONSTRAINT [DepartmentIDOfAssociate] DEFAULT (@DepartmentIDAssociate)
SELECT @ErrorVar = @@Error
IF (@ErrorVar <> 0)
BEGIN
GOTO FATAL_EXIT
END
I database di produzione, test e sviluppo non sono più sincronizzati e il DepartmentID per DepartmentName = & # 8216; RocketScience & # 8217; può essere o meno lo stesso, quindi non voglio solo dire DEFAULT (numero di riferimento). Continuo a ricevere & # 8220; Le variabili non sono consentite nell'istruzione ALTER TABLE & # 8221; non importa in che modo attacco il problema.
Qual è il modo corretto per farlo? Ho provato a nidificare anche l'istruzione select che ottiene & # 8220; Le subquery non sono consentite in questo contesto. Sono ammesse solo espressioni scalari. & # 8221;
Inoltre, ciò che sarebbe davvero fantastico potrei popolare i valori di colonna in un'istruzione invece di eseguire
{ALTER null}
{Aggiorna valori}
{ALTER not null}
passaggi. Ho letto qualcosa sul comando WITH VALUES ma non sono riuscito a farlo funzionare.
Grazie !!!
Soluzione
È possibile racchiudere il codice per trovare l'ID reparto in una funzione memorizzata e utilizzarlo nell'istruzione del vincolo DEFAULT:
CREATE FUNCTION dbo.GetDepartment()
RETURNS INT
AS
BEGIN
DECLARE @DepartmentID INT
SELECT @DepartmentID = DepartmentID
FROM Department
WHERE RealName = 'RocketScience'
RETURN @DepartmentID
END
E poi:
ALTER TABLE [Employee]
ADD [DepartmentID] INT NULL
CONSTRAINT [DepartmentIDOfAssociate] DEFAULT (dbo.GetDepartment())
Aiuta?
Marc
Altri suggerimenti
La risposta accettata ha funzionato alla grande (grazie marc_s) ma dopo averci pensato per un po 'ho deciso di fare un altro percorso.
Principalmente perché ci deve essere una funzione sul server che penso finisca per essere chiamata ogni volta che viene aggiunto un dipendente.
Se in seguito qualcuno avesse incasinato la funzione, nessuno avrebbe potuto inserire un dipendente e il motivo non sarebbe ovvio.
(Anche se questo non è vero, allora ci sono ancora funzioni extra sul server che non hanno bisogno di essere lì)
Quello che ho fatto è stato assemblare dinamicamente il comando in una variabile e quindi chiamarlo usando il comando EXECUTE.
Non solo, ma da quando ho usato la parola chiave DEFAULT con NOT NULL la tabella è stata nuovamente popolata e non ho dovuto eseguire più comandi per farlo. L'ho scoperto per fortuna ...
DECLARE @ErrorVar INT
DECLARE @DepartmentIDRocketScience INT
DECLARE @ExecuteString NVARCHAR(MAX)
SELECT @DepartmentIDRocketScience = DepartmentID
FROM Department
WHERE RealName = 'RocketScience'
SET @ExecuteString = ''
SET @ExecuteString = @ExecuteString + 'ALTER TABLE [Employee] '
SET @ExecuteString = @ExecuteString + 'ADD [DepartmentID] INT NOT NULL '
SET @ExecuteString = @ExecuteString + 'CONSTRAINT [DF_DepartmentID_RocketScienceDepartmentID] DEFAULT ' +CAST(@DepartmentIDAssociate AS NVARCHAR(MAX))
EXECUTE (@ExecuteString)
SELECT @ErrorVar = @@Error
IF (@ErrorVar <> 0)
BEGIN
GOTO FATAL_EXIT
END
Se si applica il vincolo di chiave esterna dopo aver aggiunto la colonna, è possibile utilizzare qualsiasi valore per il valore predefinito quando si modifica la tabella. Quindi è possibile eseguire un'istruzione di aggiornamento con il valore della variabile.
ALTER TABLE Employee
ADD DepartmentID INT NOT NULL
Default -1;
UPDATE Employee
SET Employee.DepartmentID = @DepartmentID
WHERE DepartmentID = -1;
ALTER TABLE Employee
ADD CONSTRAINT fk_employee_to_department FOREIGN KEY (DepartmentID)
REFERENCES Department;