ALTER TABLE con valor DEFAULT constante constante determinado mediante programación
-
20-08-2019 - |
Pregunta
Estoy intentando agregar una columna (MSSQL 2005) a una tabla (Empleado) con una restricción predeterminada de una clave primaria de otra tabla (Departamento). Entonces voy a hacer de esta columna un FK para esa tabla. Básicamente, esto asignará nuevos empleados a un departamento base basado en el nombre del departamento si no se proporciona un ID de departamento.
Esto no funciona:
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
Las bases de datos de producción, prueba y desarrollo no están sincronizadas y el ID de departamento para DepartmentName = & # 8216; RocketScience & # 8217; puede o no ser lo mismo, así que no quiero decir DEFAULT (somenumber). Sigo obteniendo & # 8220; Las variables no están permitidas en la declaración ALTER TABLE & # 8221; no importa de qué manera ataque el problema.
¿Cuál es la forma correcta de hacer esto? También he intentado anidar la instrucción select que obtiene & # 8220; Las subconsultas no están permitidas en este contexto. Solo se permiten expresiones escalares. & # 8221;
Además, lo que sería realmente genial podría rellenar los valores de columna en una declaración en lugar de hacer el
{ALTER null}
{Actualizar valores}
{ALTER not null}
pasos. Leí algo sobre el comando WITH VALUES pero no pude hacerlo funcionar.
Gracias !!!
Solución
Puede ajustar el código para encontrar su ID de departamento en una función almacenada y usarla en su declaración de restricción DEFAULT:
CREATE FUNCTION dbo.GetDepartment()
RETURNS INT
AS
BEGIN
DECLARE @DepartmentID INT
SELECT @DepartmentID = DepartmentID
FROM Department
WHERE RealName = 'RocketScience'
RETURN @DepartmentID
END
Y luego:
ALTER TABLE [Employee]
ADD [DepartmentID] INT NULL
CONSTRAINT [DepartmentIDOfAssociate] DEFAULT (dbo.GetDepartment())
¿Eso ayuda?
Marc
Otros consejos
La respuesta aceptada funcionó muy bien (Gracias marc_s) pero después de pensarlo un momento decidí ir a otra ruta.
Principalmente porque debe haber una función en el servidor que creo que termina siendo llamada cada vez que se agrega un empleado.
Si alguien se metió con la función más tarde, nadie podría ingresar a un empleado y el motivo no sería obvio.
(Incluso si eso no es cierto, todavía hay funciones adicionales en el servidor que no necesitan estar allí)
Lo que hice fue ensamblar el comando dinámicamente en una variable y luego llamarlo usando el comando EXECUTE.
No solo eso, sino que como utilicé la palabra clave DEFAULT con NOT NULL, la tabla se rellenó nuevamente y no tuve que ejecutar varios comandos para hacerlo. Lo encontré por suerte ...
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
Si aplica la restricción de clave externa después de agregar la columna, puede usar cualquier valor para el valor predeterminado al modificar la tabla. Luego puede ejecutar una declaración de actualización con su valor variable.
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;