¿Hay una manera de utilizar condicionalmente valores de columna por defecto en un comunicado INSERT..SELECT?
-
23-09-2019 - |
Pregunta
Tengo un código similar al siguiente en un procedimiento almacenado que inserta una fila en una tabla, me gustaría establecer la última columna (FieldD) a @prmSomeValue a menos que sea nula, de lo contrario sólo tiene que utilizar el valor por defecto definido para esa columna.
IF (@prmSomeValue IS NULL)
INSERT INTO MyTable (fieldA,FieldB,FieldC)
SELECT A,B,C
FROM MyOtherTable
ELSE
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,@prmSomeValue
FROM MyOtherTable
Esto funciona, pero viola el principio DRY. Estoy tratando de encontrar la manera de hacer esto con una sola instrucción de inserción. Algo a lo largo de las líneas de la siguiente pseudocódigo.
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,ISNULL(@prmSomeValue,DEFAULT)
FROM MyOtherTable
Alguien tiene alguna idea?
Actualizar - Una vuelta de tuerca más
La restricción predeterminada no es un valor literal, sino una función tal como se muestra a continuación.
...DEFAULT (suser_sname()) FOR [FieldD]
Actualizar
Finalmente despejaron y elegimos el menor de los males y acaba de copiar la función de valor por defecto en mi consulta en lugar de caer hasta el valor estándar configurado para la columna. No me encanta, pero hace el trabajo con menos repetición en mi consulta.
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,ISNULL(@prmSomeValue,suser_sname())
FROM MyOtherTable
Solución
Dado que en esencia esto es lo que SQL Server está haciendo, usted podría hacer algo como esto para evitar por lo menos dos declaraciones casi idénticas (pseudo-código):
INSERT (columnA,B,C) ... ;
IF @prmSomeValue IS NOT NULL
UPDATE ... ;
No creo que hay un camino a fundirse con el valor predeterminado.
Otros consejos
Yo diría que su método está muy bien. Una sencilla comprobación seguida por una pieza de inserción. Si usted está preocupado por SECO, encapsular la llamada para que se llama repetidamente.
Yo diría que las inserciones / actualizaciones en una base de datos puede ser costoso en algunas mesas (depende del objetivo de diseño) por lo que si usted tiene que escribir código adicional para manejar este escenario luego veo ningún problema con la solución de compromiso.
Este fuerza trabajo, depende de si usted quiere decir el valor predeterminado definido en una restricción predeterminada, o en el código? Si "restricción" se produce un error, si el "código" funciona. Editar : que la restricción media. DOH!
SELECT A,B,C,@prmSomeValue
FROM MyOtherTable
WHERE @prmSomeValue IS NOT NULL
UNION ALL
SELECT A,B,C,DEFAULT
FROM MyOtherTable
WHERE @prmSomeValue IS NULL
Sea cual sea la forma en que desea hacerlo, especificando una columna en la cláusula INSERT es necesario un valor.
Así que su primera solución es hacer lo que has ...
Algo así como este trabajo podría (aunque no muy bonita):
INSERT INTO MyTable (fieldA,FieldB,FieldC,FieldD)
SELECT A,B,C,
case when @prmSomeValue is null
then
(SELECT text FROM syscomments WHERE id IN (SELECT cdefault FROM syscolumns
WHERE id = object_id('MyTable') AND cdefault > 0))
else @prmSomeValue
end
FROM MyOtherTable