verificar varias validar registros registro mas insertar filas existe ejecutar antes agregar actualizar sql sql-server sql-server-2008 tsql

varias - validar si un registro existe en mysql



Compruebe si existe una fila, de lo contrario inserte (11)

Necesito escribir un procedimiento almacenado T-SQL que actualice una fila en una tabla. Si la fila no existe, insértela. Todos estos pasos envueltos por una transacción.

Esto es para un sistema de reserva, por lo que debe ser atómico y confiable . Debe devolver verdadero si la transacción fue confirmada y el vuelo reservado.

Soy nuevo en T-SQL y no estoy seguro de cómo usar @@rowcount . Esto es lo que he escrito hasta ahora. ¿Estoy en el camino correcto? Estoy seguro de que es un problema fácil para ti.

-- BEGIN TRANSACTION (HOW TO DO?) UPDATE Bookings SET TicketsBooked = TicketsBooked + @TicketsToBook WHERE FlightId = @Id AND TicketsMax < (TicketsBooked + @TicketsToBook) -- Here I need to insert only if the row doesn''t exists. -- If the row exists but the condition TicketsMax is violated, I must not insert -- the row and return FALSE IF @@ROWCOUNT = 0 BEGIN INSERT INTO Bookings ... (omitted) END -- END TRANSACTION (HOW TO DO?) -- Return TRUE (How to do?)


¿Asumo una sola fila para cada vuelo? Si es así:

IF EXISTS (SELECT * FROM Bookings WHERE FLightID = @Id) BEGIN --UPDATE HERE END ELSE BEGIN -- INSERT HERE END

Asumo lo que dije, ya que su forma de hacer las cosas puede sobrecargar un vuelo, ya que insertará una nueva fila cuando haya un máximo de 10 boletos y esté reservando 20.


Echa un vistazo al comando MERGE . Puede hacer UPDATE , INSERT Y DELETE en una declaración.

Aquí está una implementación de trabajo en el uso de MERGE
- Comprueba si el vuelo está lleno antes de hacer una actualización, de lo contrario hace una inserción.

if exists(select 1 from INFORMATION_SCHEMA.TABLES T where T.TABLE_NAME = ''Bookings'') begin drop table Bookings end GO create table Bookings( FlightID int identity(1, 1) primary key, TicketsMax int not null, TicketsBooked int not null ) GO insert Bookings(TicketsMax, TicketsBooked) select 1, 0 insert Bookings(TicketsMax, TicketsBooked) select 2, 2 insert Bookings(TicketsMax, TicketsBooked) select 3, 1 GO select * from Bookings

Y entonces ...

declare @FlightID int = 1 declare @TicketsToBook int = 2 --; This should add a new record merge Bookings as T using (select @FlightID as FlightID, @TicketsToBook as TicketsToBook) as S on T.FlightID = S.FlightID and T.TicketsMax > (T.TicketsBooked + S.TicketsToBook) when matched then update set T.TicketsBooked = T.TicketsBooked + S.TicketsToBook when not matched then insert (TicketsMax, TicketsBooked) values(S.TicketsToBook, S.TicketsToBook); select * from Bookings


El mejor enfoque para este problema es hacer que la columna de la base de datos sea ÚNICA

ALTER TABLE table_name ADD UNIQUE KEY

THEN INSERT IGNORE INTO table_name , el valor no se insertará si resulta en una clave duplicada / ya existe en la tabla.


Esto es algo que recientemente tuve que hacer:

set ANSI_NULLS ON set QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[cjso_UpdateCustomerLogin] ( @CustomerID AS INT, @UserName AS VARCHAR(25), @Password AS BINARY(16) ) AS BEGIN IF ISNULL((SELECT CustomerID FROM tblOnline_CustomerAccount WHERE CustomerID = @CustomerID), 0) = 0 BEGIN INSERT INTO [tblOnline_CustomerAccount] ( [CustomerID], [UserName], [Password], [LastLogin] ) VALUES ( /* CustomerID - int */ @CustomerID, /* UserName - varchar(25) */ @UserName, /* Password - binary(16) */ @Password, /* LastLogin - datetime */ NULL ) END ELSE BEGIN UPDATE [tblOnline_CustomerAccount] SET UserName = @UserName, Password = @Password WHERE CustomerID = @CustomerID END END


Estoy escribiendo mi solución. mi método no es "si" o "fusionar". mi metodo es facil

INSERT INTO TableName (col1,col2) SELECT @par1, @par2 WHERE NOT EXISTS (SELECT col1,col2 FROM TableName WHERE col1=@par1 AND col2=@par2)

Por ejemplo:

INSERT INTO Members (username) SELECT ''Cem'' WHERE NOT EXISTS (SELECT username FROM Members WHERE username=''Cem'')

Explicación:

(1) SELECCIONE col1, col2 DE TableName DONDE col1 = @ par1 Y col2 = @ par2 Selecciona de los valores buscados de TableName

(2) SELECCIONE @ par1, @ par2 DONDE NO EXISTE Toma si no existe desde (1) subconsulta

(3) Inserciones en los valores de paso de TableName (2)


Finalmente pude insertar una fila, con la condición de que no existiera, usando el siguiente modelo:

INSERT INTO table ( column1, column2, column3 ) ( SELECT $column1, $column2, $column3 WHERE NOT EXISTS ( SELECT 1 FROM table WHERE column1 = $column1 AND column2 = $column2 AND column3 = $column3 ) )

que encontré en:

http://www.postgresql.org/message-id/[email protected]


La solución completa está debajo (incluida la estructura del cursor). Muchas gracias a Cassius Porcus por el begin trans ... commit código de publicación anterior.

declare @mystat6 bigint declare @mystat6p varchar(50) declare @mystat6b bigint DECLARE mycur1 CURSOR for select result1,picture,bittot from all_Tempnogos2results11 OPEN mycur1 FETCH NEXT FROM mycur1 INTO @mystat6, @mystat6p , @mystat6b WHILE @@Fetch_Status = 0 BEGIN begin tran /* default read committed isolation level is fine */ if not exists (select * from all_Tempnogos2results11_uniq with (updlock, rowlock, holdlock) where all_Tempnogos2results11_uniq.result1 = @mystat6 and all_Tempnogos2results11_uniq.bittot = @mystat6b ) insert all_Tempnogos2results11_uniq values (@mystat6 , @mystat6p , @mystat6b) --else -- /* update */ commit /* locks are released here */ FETCH NEXT FROM mycur1 INTO @mystat6 , @mystat6p , @mystat6b END CLOSE mycur1 DEALLOCATE mycur1 go


Pase sugerencias de updlock, rowlock, holdlock cuando se prueba la existencia de la fila.

begin tran /* default read committed isolation level is fine */ if not exists (select * from Table with (updlock, rowlock, holdlock) where ...) /* insert */ else /* update */ commit /* locks are released here */

La sugerencia de bloqueo de actualización obliga a la consulta a tomar un bloqueo de actualización en la fila si ya existe, lo que evita que otras transacciones lo modifiquen hasta que confirme o retroceda.

La sugerencia de bloqueo obliga a la consulta a tomar un bloqueo de rango, evitando que otras transacciones agreguen una fila que coincida con sus criterios de filtro hasta que confirme o retroceda.

La sugerencia de bloqueo de fila obliga a bloquear la granularidad en el nivel de fila en lugar del nivel de página predeterminado, por lo que su transacción no bloqueará otras transacciones que intenten actualizar filas no relacionadas en la misma página (pero tenga en cuenta la compensación entre la contención reducida y el aumento en gastos generales de bloqueo: debe evitar tomar grandes cantidades de bloqueos de fila en una sola transacción).

Consulte http://msdn.microsoft.com/en-us/library/ms187373.aspx para obtener más información.

Tenga en cuenta que los bloqueos se toman a medida que se ejecutan las declaraciones que los llevan a ellos. La invocación de begin tran no le otorga inmunidad contra otra transacción al bloquear los bloqueos de algo antes de que llegue a ella. Debe intentar y factorizar su SQL para mantener los bloqueos durante el menor tiempo posible, confirmando la transacción tan pronto como sea posible (adquirir tarde, liberar temprano).

Tenga en cuenta que los bloqueos de nivel de fila pueden ser menos efectivos si su PK es un bigint, ya que el hash interno en SQL Server está degenerado para valores de 64 bits (valores de clave diferentes pueden ser hash para el mismo id de bloqueo).


Usted podría utilizar la funcionalidad de MERGE para lograr. De lo contrario puedes hacer:

declare @rowCount int select @rowCount=@@RowCount if @rowCount=0 begin --insert....


INSERT INTO [DatabaseName1].dbo.[TableName1] SELECT * FROM [DatabaseName2].dbo.[TableName2] WHERE [YourPK] not in (select [YourPK] from [DatabaseName1].dbo.[TableName1])


INSERT INTO table ( column1, column2, column3 ) SELECT $column1, $column2, $column3 EXCEPT SELECT column1, column2, column3 FROM table