Ik wil gegevens in mijn tabel invoegen, maar voeg alleen gegevens in die nog niet in mijn database bestaan.
Hier is mijn code:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA);
END
En de fout is:
Bericht 156, niveau 15, staat 1, procedure EmailsRecebidosInsert, regel 11
Onjuiste syntaxis bij het zoekwoord ‘WHERE’.
Antwoord 1, autoriteit 100%
in plaats van onderstaande code
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA);
END
vervangen door
BEGIN
IF NOT EXISTS (SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA)
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
END
END
Bijgewerkt:(met dank aan @Marc Durdin voor het wijzen)
Houd er rekening mee dat dit bij hoge belasting soms nog steeds mislukt, omdat een tweede verbinding de IF NOT EXISTS-test kan doorstaan voordat de eerste verbinding de INSERT uitvoert, d.w.z. een race-conditie. Zie stackoverflow.com/a/3791506/1836776voor een goed antwoord op waarom zelfs het inpakken in een transactie dit niet oplost .
Antwoord 2, autoriteit 27%
Voor degenen die op zoek zijn naar de snelste manier, heb ik onlangs kwam deze benchmarks tegenwaar blijkbaar het gebruik van “INSERT SELECT… EXCEPT SELECT…” de snelste bleek te zijn voor 50 miljoen records of meer.
Hier is een voorbeeldcode uit het artikel (het 3e codeblok was het snelst):
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
Antwoord 3, autoriteit 8%
Ik zou een samenvoeging gebruiken:
create PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
with data as (select @_DE as de, @_ASSUNTO as assunto, @_DATA as data)
merge EmailsRecebidos t
using data s
on s.de = t.de
and s.assunte = t.assunto
and s.data = t.data
when not matched by target
then insert (de, assunto, data) values (s.de, s.assunto, s.data);
END
Antwoord 4, autoriteit 5%
Probeer onderstaande code
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
select @_DE, @_ASSUNTO, @_DATA
EXCEPT
SELECT De, Assunto, Data from EmailsRecebidos
END
Antwoord 5, autoriteit 5%
Ik deed hetzelfde met SQL Server 2012 en het werkte
Insert into #table1 With (ROWLOCK) (Id, studentId, name)
SELECT '18769', '2', 'Alex'
WHERE not exists (select * from #table1 where Id = '18769' and studentId = '2')
Antwoord 6, autoriteit 3%
Andere SQL, hetzelfde principe. Alleen invoegen als de clausule in waar niet bestaat mislukt
INSERT INTO FX_USDJPY
(PriceDate,
PriceOpen,
PriceLow,
PriceHigh,
PriceClose,
TradingVolume,
TimeFrame)
SELECT '2014-12-26 22:00',
120.369000000000,
118.864000000000,
120.742000000000,
120.494000000000,
86513,
'W'
WHERE NOT EXISTS
(SELECT 1
FROM FX_USDJPY
WHERE PriceDate = '2014-12-26 22:00'
AND TimeFrame = 'W')
Antwoord 7, autoriteit 3%
Het INSERT
commando heeft geen WHERE
clausule – je moet het als volgt schrijven:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
IF NOT EXISTS (SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA)
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
END
END
Antwoord 8, autoriteit 2%
Afhankelijk van uw versie (2012?) van SQL Server, naast IF EXISTS, kunt u ook MERGE gebruiken vind ik leuk:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
( @_DE nvarchar(50)
, @_ASSUNTO nvarchar(50)
, @_DATA nvarchar(30))
AS BEGIN
MERGE [dbo].[EmailsRecebidos] [Target]
USING (VALUES (@_DE, @_ASSUNTO, @_DATA)) [Source]([De], [Assunto], [Data])
ON [Target].[De] = [Source].[De] AND [Target].[Assunto] = [Source].[Assunto] AND [Target].[Data] = [Source].[Data]
WHEN NOT MATCHED THEN
INSERT ([De], [Assunto], [Data])
VALUES ([Source].[De], [Source].[Assunto], [Source].[Data]);
END
Antwoord 9
Als uw geclusterde index alleen uit die velden bestaat, is de eenvoudige, snelle en betrouwbare optiehet gebruik van IGNORE_DUP_KEY
Als u de geclusterde index maakt met IGNORE_DUP_KEY AAN
Dan kun je gewoon gebruiken:
INSERT INTO EmailsRecebidos (De, Assunto, Data) VALUES (@_DE, @_ASSUNTO, @_DATA)
Dit zou in alle gevallen veilig moeten zijn!
Antwoord 10
Zoals uitgelegd in onderstaande code:Voer onderstaande zoekopdrachten uit en verifieer uzelf.
CREATE TABLE `table_name` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`address` varchar(255) NOT NULL,
`tele` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
Voeg een record in:
INSERT INTO table_name (name, address, tele)
SELECT * FROM (SELECT 'Nazir', 'Kolkata', '033') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_name WHERE name = 'Nazir'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_name`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Nazir | Kolkata | 033 |
+----+--------+-----------+------+
Probeer nu hetzelfde record opnieuw in te voegen:
INSERT INTO table_name (name, address, tele)
SELECT * FROM (SELECT 'Nazir', 'Kolkata', '033') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_name WHERE name = 'Nazir'
) LIMIT 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Nazir | Kolkata | 033 |
+----+--------+-----------+------+
Voeg een ander record in:
INSERT INTO table_name (name, address, tele)
SELECT * FROM (SELECT 'Santosh', 'Kestopur', '044') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_name WHERE name = 'Santosh'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_name`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Nazir | Kolkata | 033 |
| 2 | Santosh| Kestopur | 044 |
+----+--------+-----------+------+
Antwoord 11
Je zou de opdracht GO
kunnen gebruiken. Dat zal de uitvoering van SQL-instructies herstarten na een fout. In mijn geval heb ik een paar 1000 INSERT-instructies, waar een handvol van die records al in de database bestaan, ik weet alleen niet welke.
Ik ontdekte dat na het verwerken van een paar 100, de uitvoering gewoon stopt met een foutmelding dat het niet kan INSERT
omdat het record al bestaat. Best vervelend, maar het plaatsen van een GO
loste dit op. Het is misschien niet de snelste oplossing, maar snelheid was niet mijn probleem.
GO
INSERT INTO mytable (C1,C2,C3) VALUES(1,2,3)
GO
INSERT INTO mytable (C1,C2,C3) VALUES(4,5,6)
etc ...