T-SQL: uso de CASE en una instrucción UPDATE para actualizar ciertas columnas dependiendo de una condición

108

Me pregunto si esto es posible. Quiero actualizar la columna x si una condición es verdadera; de lo contrario, la columna y se actualizaría

UPDATE table SET
     (CASE (CONDITION) WHEN TRUE THEN columnx
                       ELSE columny
      END)
= 25

He buscado por todas partes, he probado algunas cosas y no he podido encontrar una solución. Creo que no es posible, pero pensé en preguntar aquí y ver si alguien lo ha hecho antes. Gracias por adelantado.

pqsk
fuente
Suponiendo que todos estén en la misma tabla, sí. Siempre puede ejecutarlo en una transacción y retroceder en caso de error, para verlo usted mismo.
OMG Ponies
No estoy seguro de lo que quieres decir. Intenté poner un condicional para la columna, pero no funciona. Funciona para una declaración de selección, pero no para una declaración de actualización. (Seleccione (caso (condición) cuando sea verdadero, luego columnx, si no, final de la columna) de myTable ... la actualización no funciona, y puedo ver por qué. t parece una manera de hacer que el trabajo.
pqsk

Respuestas:

188

No puede usar una condición para cambiar la estructura de su consulta, solo los datos involucrados. Podrías hacer esto:

update table set
    columnx = (case when condition then 25 else columnx end),
    columny = (case when condition then columny else 25 end)

Esto es semánticamente igual, pero tenga en cuenta que ambas columnas siempre se actualizarán . Esto probablemente no le cause ningún problema, pero si tiene un volumen transaccional alto, esto podría causar problemas de concurrencia.

La única forma de hacer específicamente lo que está pidiendo es utilizar SQL dinámico. Sin embargo, esto es algo de lo que le animo a que se mantenga alejado. Es casi seguro que la solución anterior será suficiente para lo que busca.

Adam Robinson
fuente
Estoy de acuerdo con el SQL dinámico. Entonces, ¿mis datos se verán afectados? Quiero decir que no quiero que se cambie por cierta condición. ¿Entonces simplemente reinsertará lo que ya está allí? Es posible que la cantidad de visitas a la base de datos no sea tan mala.
pqsk
@pqsk: esto no debería afectar sus datos, solo debería reinsertar lo que ya está allí para cualquier columna que no se suponga que se vea afectada.
Adam Robinson
Gracias. Voy a seguir con esto. Tan simple que incluso un cavernícola puede hacerlo. jaja.
pqsk
1
@AdamRobinson 1,5 años se pasan hacen que sabes de algún modo más eficiente para actualizar sólo una columna
@Somebodyisintrouble: la única forma de actualizar una columna es usar una consulta diferente.
Adam Robinson
23
UPDATE  table
SET     columnx = CASE WHEN condition THEN 25 ELSE columnx END,
        columny = CASE WHEN condition THEN columny ELSE 25 END
Quassnoi
fuente
1
¿Copiaste la respuesta de Adam o fue sacada de otra parte? jaja. Solo me di cuenta de eso.
pqsk
1
@pqsk: Nuestras respuestas fueron con ~ 1 minuto de diferencia, así que imagino que hice clic en enviar un poco más rápido;)
Adam Robinson
23
@pqsk: sí, simplemente copié la respuesta de Adam, 23segundos antes de que la publicara. ¡Soy un copista rápido!
Quassnoi
2
@pqsk: si coloca el cursor sobre el * min ago, le mostrará la hora exacta en que se publicó.
Quassnoi
2
Para ser justos, aunque ambos son iguales: si el de Adam hubiera salido después del tuyo, sí elaboró ​​algo más. Por eso marqué la suya como la respuesta. Pero gracias.
pqsk
4

ingrese la descripción de la imagen aquí

Quiero cambiar o actualizar mi ContactNo a 8018070999 donde hay 8018070777 usando la declaración de caso

update [Contacts] set contactNo=(case 
when contactNo=8018070777 then 8018070999
else
contactNo
end)

ingrese la descripción de la imagen aquí

Debendra Dash
fuente
1
por eso, ¿por qué no usar esta consulta ACTUALIZAR [Contactos] SET contactNo = 8018070999 DONDE contactNo = 8018070777
NewGuy
4

Sé que esta es una pregunta muy antigua, pero funcionó para mí:

UPDATE TABLE SET FIELD1 =
CASE 
WHEN FIELD1 = Condition1 THEN 'Result1'
WHEN FIELD1 = Condition2 THEN 'Result2'
WHEN FIELD1 = Condition3 THEN 'Result3'
END;

Saludos

Víctor Eduardo Salazar Ramírez
fuente
1

Sé que esta es una pregunta muy antigua y el problema está marcado como solucionado. Sin embargo, si alguien con un caso como el mío donde la tabla tiene un disparador para el registro de datos en eventos de actualización, esto causará problemas. Ambas columnas recibirán la actualización y el registro hará entradas inútiles. La forma en que lo hice

IF (CONDITION) IS TRUE
BEGIN
    UPDATE table SET columnx = 25
END
ELSE
BEGIN
    UPDATE table SET columny = 25
END

Ahora bien, esto tiene otro beneficio de que no tiene escrituras innecesarias en la mesa como las soluciones anteriores.

Duro
fuente
¡Este es un buen punto y una buena alternativa! Ya no estoy trabajando en el código original que conduce a este hilo, pero siempre es bueno tener diferentes soluciones y creo que esta es una buena solución
pqsk
-1

Creo que puede omitir la actualización de las columnas "no deseadas" ajustando las otras respuestas de la siguiente manera:
update table set columnx = (case when condition1 then 25 end), columny = (case when condition2 then 25 end)

Según tengo entendido, esto se actualizará solo cuando se cumpla la condición.

Después de leer todos los comentarios, este es el más eficiente:
Update table set ColumnX = 25 where Condition1 Update table set ColumnY = 25 where Condition1

Tabla de muestra:
CREATE TABLE [dbo].[tblTest]( [ColX] [int] NULL, [ColY] [int] NULL, [ColConditional] [bit] NULL, [id] [int] IDENTITY(1,1) NOT NULL ) ON [PRIMARY]
Datos de muestra:
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (1, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (2, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 1, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 2, null)

ahora supongo que puede escribir un condicional que maneje valores nulos. Para mi ejemplo, supongo que ha escrito un condicional que se evalúa como Verdadero, Falso o Nulo. Si necesita ayuda con esto, hágamelo saber y haré todo lo posible.

Ahora, al ejecutar estas dos líneas de código, de hecho cambia X a 25 si y solo si ColConditional es True (1) e Y a 25 si y solo si ColConditional es False (0)

Update tblTest set ColX = 25 where ColConditional = 1 Update tblTest set ColY = 25 where ColConditional = 0

PD: El caso nulo nunca se mencionó en la pregunta original ni en ninguna actualización de la pregunta, pero como puede ver, esta respuesta muy simple los maneja de todos modos.

John Greiner
fuente
1
En realidad, esto no funciona. Por un lado, si la columna permite valores nulos, cuando no se cumple la condición, se asigna un valor nulo. En el caso de que no se permitan valores nulos, la actualización fallará. Su consulta "eficiente" final es SQL inválido, al menos en TSQL. ¿Probó esto en un motor específico y funcionó para usted?
pqsk
Probé esto en SQL Server 2005 y funciona perfectamente como se muestra. Seguro que me gustaría saber por qué se votó en contra y un ejemplo que muestra que el valor NULL se actualiza, porque en mi prueba anterior, el valor nulo no se actualiza. Siempre he pensado que la respuesta más simple es la mejor y si estoy tratando con una base de datos con millones de registros seguro que no quiero ir actualizando filas innecesarias.
John Greiner