values postgres not into example create sql sql-server

sql - postgres - INSERTE VALORES DONDE NO EXISTE



mysql insert values where not exists (5)

De acuerdo, estoy intentando mejorar la página de entrada de datos de mi asp para asegurar que la entrada que va a mi tabla de datos sea única.

Así que en esta tabla tengo SoftwareName y SoftwareType. Estoy intentando obtenerlo, por lo que si la página de entrada envía una consulta de inserción con parámetros que coinciden con lo que hay en la tabla (el mismo título y tipo), se genera un error y no se ingresan los datos.

Algo como esto:

INSERT INTO tblSoftwareTitles( SoftwareName, SoftwareSystemType) VALUES(@SoftwareName,@SoftwareType) WHERE NOT EXISTS (SELECT SoftwareName FROM tblSoftwareTitles WHERE Softwarename = @SoftwareName AND SoftwareType = @Softwaretype)

Entonces, esta sintaxis funciona muy bien para seleccionar columnas de una tabla a otra sin que se ingresen duplicados, pero no parece querer trabajar con una consulta de inserción parametrizada. ¿Puede alguien ayudarme con esto?

Editar:

Aquí está el código que estoy usando en mi método de inserción ASP

private void ExecuteInsert(string name, string type) { //Creates a new connection using the HWM string using (SqlConnection HWM = new SqlConnection(GetConnectionStringHWM())) { //Creates a sql string with parameters string sql = " INSERT INTO tblSoftwareTitles( " + " SoftwareName, " + " SoftwareSystemType) " + " SELECT " + " @SoftwareName, " + " @SoftwareType " + " WHERE NOT EXISTS " + " ( SELECT 1 " + " FROM tblSoftwareTitles " + " WHERE Softwarename = @SoftwareName " + " AND SoftwareSystemType = @Softwaretype); "; //Opens the connection HWM.Open(); try { //Creates a Sql command using (SqlCommand addSoftware = new SqlCommand{ CommandType = CommandType.Text, Connection = HWM, CommandTimeout = 300, CommandText = sql}) { //adds parameters to the Sql command addSoftware.Parameters.Add("@SoftwareName", SqlDbType.NVarChar, 200).Value = name; addSoftware.Parameters.Add("@SoftwareType", SqlDbType.Int).Value = type; //Executes the Sql addSoftware.ExecuteNonQuery(); } Alert.Show("Software title saved!"); } catch (System.Data.SqlClient.SqlException ex) { string msg = "Insert Error:"; msg += ex.Message; throw new Exception(msg); } } }


¿Ingnorar la restricción única duplicada no es una solución?

INSERT IGNORE INTO tblSoftwareTitles...


Haría esto usando y una declaración IF :

IF NOT EXISTS ( SELECT 1 FROM tblSoftwareTitles WHERE Softwarename = @SoftwareName AND SoftwareSystemType = @Softwaretype ) BEGIN INSERT tblSoftwareTitles (SoftwareName, SoftwareSystemType) VALUES (@SoftwareName, @SoftwareType) END;

Podrías hacerlo sin IF usando SELECT

INSERT tblSoftwareTitles (SoftwareName, SoftwareSystemType) SELECT @SoftwareName,@SoftwareType WHERE NOT EXISTS ( SELECT 1 FROM tblSoftwareTitles WHERE Softwarename = @SoftwareName AND SoftwareSystemType = @Softwaretype );

Ambos métodos son susceptibles a una condición de carrera , así que si bien todavía usaría uno de los anteriores para insertar, pero puede proteger inserciones duplicadas con una restricción única:

CREATE UNIQUE NONCLUSTERED INDEX UQ_tblSoftwareTitles_Softwarename_SoftwareSystemType ON tblSoftwareTitles (SoftwareName, SoftwareSystemType);

Ejemplo en SQL-Fiddle

APÉNDICE

En SQL Server 2008 o posterior, puede usar MERGE con HOLDLOCK para eliminar la posibilidad de una condición de carrera (que aún no es un sustituto de una restricción única).

MERGE tblSoftwareTitles WITH (HOLDLOCK) AS t USING (VALUES (@SoftwareName, @SoftwareType)) AS s (SoftwareName, SoftwareSystemType) ON s.Softwarename = t.SoftwareName AND s.SoftwareSystemType = t.SoftwareSystemType WHEN NOT MATCHED BY TARGET THEN INSERT (SoftwareName, SoftwareSystemType) VALUES (s.SoftwareName, s.SoftwareSystemType);

Ejemplo de Merge en SQL Fiddle


Hay una gran solución para este problema, puede usar la palabra clave Merge de Sql

Merge MyTargetTable hba USING (SELECT Id = 8, Name = ''Product Listing Message'') temp ON temp.Id = hba.Id WHEN NOT matched THEN INSERT (Id, Name) VALUES (temp.Id, temp.Name);

Puedes comprobarlo antes de seguir, a continuación se muestra la muestra.

IF OBJECT_ID (''dbo.TargetTable'') IS NOT NULL DROP TABLE dbo.TargetTable GO CREATE TABLE dbo.TargetTable ( Id INT NOT NULL, Name VARCHAR (255) NOT NULL, CONSTRAINT PK_TargetTable PRIMARY KEY (Id) ) GO INSERT INTO dbo.TargetTable (Name) VALUES (''Unknown'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''Mapping'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''Update'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''Message'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''Switch'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''Unmatched'') GO INSERT INTO dbo.TargetTable (Name) VALUES (''ProductMessage'') GO Merge MyTargetTable hba USING (SELECT Id = 8, Name = ''Listing Message'') temp ON temp.Id = hba.Id WHEN NOT matched THEN INSERT (Id, Name) VALUES (temp.Id, temp.Name);


Más de un enlace de comentarios para una lectura adicional sugerida ... Aquí se puede encontrar un artículo de blog realmente bueno que evalúa varias formas de realizar esta tarea.

Usan algunas técnicas: "Insertar donde no existe", declaración "Combinar", "Insertar excepto" y su "combinación izquierda" típica para ver qué camino es el más rápido para realizar esta tarea.

El código de ejemplo utilizado para cada técnica es el siguiente (copiar / pegar directamente desde su página):

INSERT INTO #table1 (Id, guidd, TimeAdded, ExtraData) SELECT Id, guidd, TimeAdded, ExtraData FROM #table2 WHERE NOT EXISTS (Select Id, guidd From #table1 WHERE #table1.id = #table2.id) ----------------------------------- MERGE #table1 as [Target] USING (select Id, guidd, TimeAdded, ExtraData from #table2) as [Source] (id, guidd, TimeAdded, ExtraData) on [Target].id =[Source].id WHEN NOT MATCHED THEN INSERT (id, guidd, TimeAdded, ExtraData) VALUES ([Source].id, [Source].guidd, [Source].TimeAdded, [Source].ExtraData); ------------------------------ INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData) SELECT id, guidd, TimeAdded, ExtraData from #table2 EXCEPT SELECT id, guidd, TimeAdded, ExtraData from #table1 ------------------------------ INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData) SELECT #table2.id, #table2.guidd, #table2.TimeAdded, #table2.ExtraData FROM #table2 LEFT JOIN #table1 on #table1.id = #table2.id WHERE #table1.id is null

¡Es una buena lectura para aquellos que buscan velocidad! En SQL 2014, el método Insertar-Excepto resultó ser el más rápido para 50 millones de registros o más.


Esto no es una respuesta. Solo quiero mostrar que IF NOT EXISTS(...) INSERT método IF NOT EXISTS(...) INSERT no es seguro. Tienes que ejecutar la primera Session #1 y luego la Session #2 . Después de v #2 verá que sin un índice UNIQUE podría obtener pares duplicados (SoftwareName,SoftwareSystemType) . La demora de la sesión # 1 se usa para darle tiempo suficiente para ejecutar el segundo script (sesión # 2). Podrías reducir este retraso.

Sesión # 1 (SSMS> Nueva consulta> F5 (Ejecutar))

CREATE DATABASE DemoEXISTS; GO USE DemoEXISTS; GO CREATE TABLE dbo.Software( SoftwareID INT PRIMARY KEY, SoftwareName NCHAR(400) NOT NULL, SoftwareSystemType NVARCHAR(50) NOT NULL ); GO INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (1,''Dynamics AX 2009'',''ERP''); INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (2,''Dynamics NAV 2009'',''SCM''); INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (3,''Dynamics CRM 2011'',''CRM''); INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (4,''Dynamics CRM 2013'',''CRM''); INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (5,''Dynamics CRM 2015'',''CRM''); GO /* CREATE UNIQUE INDEX IUN_Software_SoftwareName_SoftareSystemType ON dbo.Software(SoftwareName,SoftwareSystemType); GO */ -- Session #1 BEGIN TRANSACTION; UPDATE dbo.Software SET SoftwareName=''Dynamics CRM'', SoftwareSystemType=''CRM'' WHERE SoftwareID=5; WAITFOR DELAY ''00:00:15'' -- 15 seconds delay; you have less than 15 seconds to switch SSMS window to session #2 UPDATE dbo.Software SET SoftwareName=''Dynamics AX'', SoftwareSystemType=''ERP'' WHERE SoftwareID=1; COMMIT --ROLLBACK PRINT ''Session #1 results:''; SELECT * FROM dbo.Software;

Sesión # 2 (SSMS> Nueva consulta> F5 (Ejecutar))

USE DemoEXISTS; GO -- Session #2 DECLARE @SoftwareName NVARCHAR(100), @SoftwareSystemType NVARCHAR(50); SELECT @SoftwareName=N''Dynamics AX'', @SoftwareSystemType=N''ERP''; PRINT ''Session #2 results:''; IF NOT EXISTS(SELECT * FROM dbo.Software s WHERE s.SoftwareName=@SoftwareName AND s.SoftwareSystemType=@SoftwareSystemType) BEGIN PRINT ''Session #2: INSERT''; INSERT INTO dbo.Software(SoftwareID,SoftwareName,SoftwareSystemType) VALUES (6,@SoftwareName,@SoftwareSystemType); END PRINT ''Session #2: FINISH''; SELECT * FROM dbo.Software;

Resultados:

Session #1 results: SoftwareID SoftwareName SoftwareSystemType ----------- ----------------- ------------------ 1 Dynamics AX ERP 2 Dynamics NAV 2009 SCM 3 Dynamics CRM 2011 CRM 4 Dynamics CRM 2013 CRM 5 Dynamics CRM CRM Session #2 results: Session #2: INSERT Session #2: FINISH SoftwareID SoftwareName SoftwareSystemType ----------- ----------------- ------------------ 1 Dynamics AX ERP <-- duplicate (row updated by session #1) 2 Dynamics NAV 2009 SCM 3 Dynamics CRM 2011 CRM 4 Dynamics CRM 2013 CRM 5 Dynamics CRM CRM 6 Dynamics AX ERP <-- duplicate (row inserted by session #2)