أريد إدراج بيانات في الجدول الخاص بي ، ولكن إدراج فقط غير موجود في قاعدة البيانات الخاصة بي!
هنا هو الكود الخاص بي:
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
والخطأ هو:
Msg 156 ، المستوى 15 ، الحالة 1 ، الإجراء EmailsRecebidosInsert ، السطر 11
بناء جملة غير صحيح بالقرب من الكلمة الأساسية "أين".
بدلا من أدناه رمز
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
استبدل ب
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
تم التحديث: (بفضلMarc Durdin للإشارة)
تجدر الإشارة إلى أنه في حالة وجود حمل كبير ، سيظل هذا الأمر يفشل في بعض الأحيان ، لأن الاتصال الثاني يمكن أن يجتاز اختبار IF NOT EXISTS قبل تنفيذ الاتصال الأول INSERT ، أي شرط السباق. راجع stackoverflow.com/a/3791506/1836776 للحصول على إجابة جيدة حول السبب في أن الالتفاف في معاملة لا يحل هذا.
بالنسبة لأولئك الذين يبحثون عن الطريقة الأسرع ، لقد صادفت مؤخرًا هذه المعايير حيث يبدو أن استخدام "INSERT SELECT ... EXCEPT SELECT ..." هو الأسرع لـ 50 مليون سجل أو أكثر من.
إليك بعض نماذج التعليمات البرمجية من المقالة (كانت الكتلة الثالثة من التعليمات البرمجية هي الأسرع):
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
أود استخدام دمج:
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
حاول أدناه رمز
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
لا يحتوي أمر INSERT
على جملة WHERE
- يجب عليك كتابتها كما يلي:
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
لقد فعلت نفس الشيء مع SQL Server 2012 وقد عملت
Insert into #table1 With (ROWLOCK) (Id, studentId, name)
SELECT '18769', '2', 'Alex'
WHERE not exists (select * from #table1 where Id = '18769' and studentId = '2')
اعتمادًا على الإصدار (2012؟) من SQL Server بصرف النظر عن IF EXISTS ، يمكنك أيضًا استخدام دمج مثل ذلك:
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
كما هو موضح في التعليمات البرمجية أدناه: تنفيذ الاستعلامات أدناه والتحقق من نفسك (أنها ذاتية التوضيح)
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;
إدراج سجل:
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 |
+----+--------+-----------+------+
الآن ، حاول إدراج السجل نفسه مرة أخرى:
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 |
+----+--------+-----------+------+
إدراج سجل مختلف:
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 |
+----+--------+-----------+------+
يمكنك استخدام الأمر GO. سيؤدي ذلك إلى إعادة تشغيل تنفيذ عبارات SQL بعد حدوث خطأ. في حالتي ، لدي بضعة آلاف من عبارات INSERT ، حيث توجد بالفعل حفنة من هذه السجلات في قاعدة البيانات ، ولا أعرف أي منها. لقد وجدت أنه بعد معالجة عدد قليل من 100 ، يتوقف التنفيذ فقط مع ظهور رسالة خطأ أنه لا يمكن إدراجه لأن السجل موجود بالفعل. مزعج جدا ، ولكن وضع GO حل هذا. قد لا يكون الحل الأسرع ، لكن السرعة لم تكن مشكلتي.
GO
INSERT INTO mytable (C1,C2,C3) VALUES(1,2,3)
GO
INSERT INTO mytable (C1,C2,C3) VALUES(4,5,6)
etc ...