una tablas recomendaciones porque optimizar lenta las dañan cuello consultas consulta consejos como botella agilizar sql sql-server sql-server-2005 tsql

sql - tablas - SI EXISTE, LUEGO SELECCIONE MÁS INSERTAR Y LUEGO SELECCIONAR



porque se dañan las tablas en mysql (7)

¿Cómo se dice lo siguiente en Microsoft SQL Server 2005:

IF EXISTS (SELECT * FROM Table WHERE FieldValue='''') THEN SELECT TableID FROM Table WHERE FieldValue='''' ELSE INSERT INTO TABLE(FieldValue) VALUES('''') SELECT TableID FROM Table WHERE TableID=SCOPE_IDENTITY() END IF

Lo que estoy tratando de hacer es ver si ya hay un valor de campo en blanco, y si lo hay, devolver ese TableID; de lo contrario, inserte un valor de campo en blanco y devuelva la clave primaria correspondiente.


Estabas cerca:

IF EXISTS (SELECT * FROM Table WHERE FieldValue='''') SELECT TableID FROM Table WHERE FieldValue='''' ELSE BEGIN INSERT INTO TABLE (FieldValue) VALUES ('''') SELECT TableID FROM Table WHERE TableID=SCOPE_IDENTITY() END


Solo tienes que cambiar la estructura del if...else..endif algo así:

if exists(select * from Table where FieldValue='''') then begin select TableID from Table where FieldValue='''' end else begin insert into Table (FieldValue) values ('''') select TableID from Table where TableID = scope_identity() end

También podrías hacer:

if not exists(select * from Table where FieldValue='''') then begin insert into Table (FieldValue) values ('''') end select TableID from Table where FieldValue=''''

O:

if exists(select * from Table where FieldValue='''') then begin select TableID from Table where FieldValue='''' end else begin insert into Table (FieldValue) values ('''') select scope_identity() as TableID end


DECLARE @t1 TABLE ( TableID int IDENTITY, FieldValue varchar(20) ) --<< No empty string IF EXISTS ( SELECT * FROM @t1 WHERE FieldValue = '''' ) BEGIN SELECT TableID FROM @t1 WHERE FieldValue='''' END ELSE BEGIN INSERT INTO @t1 (FieldValue) VALUES ('''') SELECT SCOPE_IDENTITY() AS TableID END --<< A record with an empty string already exists IF EXISTS ( SELECT * FROM @t1 WHERE FieldValue = '''' ) BEGIN SELECT TableID FROM @t1 WHERE FieldValue='''' END ELSE BEGIN INSERT INTO @t1 (FieldValue) VALUES ('''') SELECT SCOPE_IDENTITY() AS TableID END


IF EXISTS (SELECT 1 FROM Table WHERE FieldValue='''') BEGIN SELECT TableID FROM Table WHERE FieldValue='''' END ELSE BEGIN INSERT INTO TABLE(FieldValue) VALUES('''') SELECT SCOPE_IDENTITY() AS TableID END

Consulte aquí para obtener más información sobre IF ELSE

Nota: escrito sin una instalación de SQL Server a mano para verificar esto pero creo que es correcto

Además, he cambiado el bit EXISTS para hacer SELECCIONAR 1 en lugar de SELECCIONAR * ya que no me importa lo que se devuelve dentro de un EXISTO, siempre y cuando algo haya cambiado también el bit SCOPE_IDENTITY () para devolver solo la identidad asumiendo que TableID es la columna de identidad


Parece que tu mesa no tiene llave. Debería poder simplemente probar INSERT : si es un duplicado, la restricción de clave morderá y INSERT . No se preocupe: solo necesita asegurarse de que la aplicación no vea / ignore el error. Cuando dices ''clave primaria'' presumiblemente quieres decir valor de IDENTITY . Eso está muy bien, pero también necesita una restricción clave (por ejemplo, UNIQUE ) en su clave natural.

Además, me pregunto si su procedimiento está haciendo demasiado. Considere tener procedimientos separados para las acciones ''crear'' y ''leer'', respectivamente.


Debe hacer esto en la transacción para asegurarse de que dos clientes simultáneos no inserten el mismo fieldValue dos veces:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION DECLARE @id AS INT SELECT @id = tableId FROM table WHERE fieldValue=@newValue IF @id IS NULL BEGIN INSERT INTO table (fieldValue) VALUES (@newValue) SELECT @id = SCOPE_IDENTITY() END SELECT @id COMMIT TRANSACTION

también puede usar el bloqueo comprobado doble para reducir la sobrecarga de bloqueo

DECLARE @id AS INT SELECT @id = tableID FROM table (NOLOCK) WHERE fieldValue=@newValue IF @id IS NULL BEGIN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SELECT @id = tableID FROM table WHERE fieldValue=@newValue IF @id IS NULL BEGIN INSERT INTO table (fieldValue) VALUES (@newValue) SELECT @id = SCOPE_IDENTITY() END COMMIT TRANSACTION END SELECT @id

En cuanto a por qué ISOLATION LEVEL SERIALIZABLE es necesario, cuando se encuentra dentro de una transacción serializable, el primer SELECT que golpea la tabla crea un bloqueo de rango que cubre el lugar donde debe estar el registro, para que nadie más pueda insertar el mismo registro hasta que finalice la transacción.

Sin AISLAMIENTO NIVEL SERIALIZABLE, el nivel de aislamiento predeterminado (LECTURA COMPROMETIDA) no bloquearía la tabla en el momento de la lectura, por lo que entre SELECCIONAR y ACTUALIZAR, alguien aún podría insertar. Las transacciones con nivel de aislamiento LECTURA COMPROMETIDA no provocan que SELECCIONAR se bloquee. Las transacciones con READATABLE READS bloquean el registro (si se encuentra) pero no el espacio.


create schema tableName authorization dbo go IF OBJECT_ID (''tableName.put_fieldValue'', ''P'' ) IS NOT NULL drop proc tableName.put_fieldValue go create proc tableName.put_fieldValue(@fieldValue int) as declare @tableid int = 0 select @tableid = tableid from table where fieldValue='''' if @tableid = 0 begin insert into table(fieldValue) values('''') select @tableid = scope_identity() end return @tableid go declare @tablid int = 0 exec @tableid = tableName.put_fieldValue('''')