¿Uno de mis campos DB NO ES NULO?
Pregunta
Tengo que lidiar con una tabla donde hay un conjunto de campos cada uno seguido de un segundo campo que contendrá un nuevo valor sugerido hasta que se confirme este cambio.
Se parece un poco a esto:
refID field1 newField1 field2 newField2 ...
refID es un valor de ID que se vincula a una tabla maestra. Una fila en la tabla maestra puede tener n filas en mi tabla de detalles. Los tipos de datos incluyen ints, strings y dateTimes.
Ahora, estoy buscando tener una consulta que me diga, dada una refID, si hay algún cambio sugerido en la tabla de detalles.
Estaba jugando un poco con algunas selecciones de UNION, con COALESCE () e ISNULL () ... pero todos esos intentos parecían un poco raros en el mejor de los casos. La base de datos es MS-SQL-Server 2005.
Para aclarar mi problema:
--this is a simplification of the details table in question
CREATE TABLE [dbo].[TEST_TABLE](
[ID] [int] IDENTITY(1,1) NOT NULL,
[refID] [int] NOT NULL,
[firstName] [varchar](50) NULL,
[newFirstName] [varchar](50) NULL,
[lastName] [varchar](50) NULL,
[newLastName] [varchar](50) NULL
)
--here we insert a detail row ... one of many that might exist for the master table (e.g. data about the company)
insert into TEST_TABLE(refID, firstName, lastName) values(666, 'Bill', 'Ballmer')
--this is what happens when a user saves a suggested change
update TEST_TABLE SET newLastName = 'Gates' where ID = 1
--and this is what happens when this suggestion is accepted by a second user
update TEST_TABLE set lastName=newLastName, newLastName = NULL where ID = 1
Solución
Esta es la solución más limpia que se me ocurre. Debería repetir la lógica para cada elemento de datos (col1, col2, etc.):
DECLARE @RefID int, @Changes bit
SET @Changes = 0 --No changes by default
SET @RefID = 42 --Your RefID
IF EXISTS(SELECT * FROM MyDetailTable
WHERE RefID = @RefID
AND (
(Col1 IS NULL AND NewCol1 IS NOT NULL)
OR
(Col1 IS NOT NULL AND NewCol1 IS NULL)
OR
(Col1 <> Col2)
))
SET @Changes = 1
Otros consejos
Modifiqué la solución de randolphos.
select
refID ,
case when
newField1 is not null or
newField2 is not null or
...
then 1 else 0 end haschanged
from myTable
where refID = @refID
Actualización: básicamente lo que dijo Aron Aalton en otro formato de salida.
Aquí hay una consulta simple:
SELECT TOP 1 1 as found FROM [dbo].[TEST_TABLE] t WHERE COALESCE(t.newFirstName,t.newLastName) IS NOT NULL AND t.refID = 1
Esta consulta devolverá una sola fila si hay cambios propuestos para un refID
(basado en el ejemplo en su pregunta).
Para su tabla real, por supuesto, necesitaría enumerar cada una de las columnas 'newValue'
como argumentos en la función COALESCE. (En la lista de fusión, recomiendo explícitamente convertir cualquier VARCHAR que no sea VARCHAR, solo para dejar en claro que cada expresión en la lista es del mismo tipo de datos.
Si prefiere usar una expresión CASE en lugar de COALESCE:
SELECT TOP 1 1 as found FROM [dbo].[TEST_TABLE] t WHERE CASE WHEN t.newFirstName IS NOT NULL THEN 1 WHEN t.newLastName IS NOT NULL THEN 1 ELSE NULL END IS NOT NULL AND t.refID = 1
¿Este esquema ya está definido y en producción? De lo contrario, recomendaría encarecidamente tener una tabla de 'cambios' separada de alguna descripción, tal vez use fieldname, fieldvalue donde fieldvalue es una variable sql_variant.
No creo que su estructura existente se vea bien cuando los valores sean 'aceptados' (supongo que nulos) especialmente porque no conservará ningún historial de auditoría con este enfoque.
No puedo probar esto, pero quizás:
select (field1 is not null and field2 is not null) as ChangesMade where refID = @id