الكلمة الأساسية IDENTITY هي خاصية في SQL Server. عندما يتم تعريف عمود جدول بخاصية هوية، سيتم إنشاء قيمته كقيمة تزايدية يتم إنشاؤها تلقائيًا . يتم إنشاء هذه القيمة بواسطة الخادم تلقائيًا. ولذلك، لا يمكننا إدخال قيمة يدويًا في عمود الهوية كمستخدم. ومن ثم، إذا وضعنا علامة على عمود كهوية، فسيقوم SQL Server بملءه بطريقة الزيادة التلقائية.
بناء الجملة
فيما يلي بناء الجملة لتوضيح استخدام خاصية IDENTITY في SQL Server:
IDENTITY[(seed, increment)]
يتم شرح معلمات بناء الجملة أعلاه أدناه:
دعونا نفهم هذا المفهوم من خلال مثال بسيط.
لنفترض أن لدينا '' طالب 'الجدول، ونريد هوية الطالب ليتم إنشاؤها تلقائيا. لدينا بداية هوية الطالب 10 وأريد زيادتها بمقدار 1 مع كل معرف جديد. في هذا السيناريو، يجب تحديد القيم التالية.
بذرة: 10
زيادة راتب: 1
CREATE TABLE Student ( StudentID INT IDENTITY(10, 1) PRIMARY KEY NOT NULL, )
ملاحظة: يُسمح بعمود تعريف واحد فقط لكل جدول في SQL Server.
مثال على هوية خادم SQL
دعونا نفهم كيف يمكننا استخدام خاصية الهوية في الجدول. يمكن تعيين خاصية الهوية في العمود إما عند إنشاء الجدول الجديد أو بعد إنشائه. وسنرى هنا كلتا الحالتين مع الأمثلة.
خاصية IDENTITY مع جدول جديد
سيقوم البيان التالي بإنشاء جدول جديد بخاصية الهوية في قاعدة البيانات المحددة:
CREATE TABLE person ( PersonID INT IDENTITY(10,1) PRIMARY KEY NOT NULL, Fullname VARCHAR(100) NOT NULL, Occupation VARCHAR(50), Gender VARCHAR(10) NOT NULL );
بعد ذلك، سوف نقوم بإدراج صف جديد في هذا الجدول مع انتاج جملة لرؤية معرف الشخص الذي تم إنشاؤه تلقائيًا:
INSERT INTO person(Fullname, Occupation, Gender) OUTPUT inserted.PersonID VALUES('Sara Jackson', 'HR', 'Female');
سيؤدي تنفيذ هذا الاستعلام إلى عرض الإخراج أدناه:
يوضح هذا الإخراج أنه تم إدراج الصف الأول بالقيمة عشرة في الملف معرف الشخص العمود كما هو محدد في عمود هوية تعريف الجدول.
دعونا نقوم بإدراج صف آخر في جدول الشخص على النحو التالي:
INSERT INTO person(Fullname, Occupation, Gender) OUTPUT inserted.* VALUES('Mark Boucher', 'Cricketer', 'Male'), ('Josh Phillip', 'Writer', 'Male');
سيعود هذا الاستعلام بالإخراج التالي:
يوضح هذا الإخراج أنه تم إدراج الصف الثاني بالقيمة 11 والصف الثالث بالقيمة 12 في عمود معرف الشخص.
خاصية IDENTITY مع الجدول الموجود
سنشرح هذا المفهوم أولاً بحذف الجدول أعلاه وإنشائه بدون خاصية الهوية. قم بتنفيذ العبارة التالية لإسقاط الجدول:
DROP TABLE person;
بعد ذلك، سنقوم بإنشاء جدول باستخدام الاستعلام أدناه:
CREATE TABLE person ( Fullname VARCHAR(100) NOT NULL, Occupation VARCHAR(50), Gender VARCHAR(10) NOT NULL );
إذا أردنا إضافة عمود جديد بخاصية الهوية في جدول موجود، فنحن بحاجة إلى استخدام أمر ALTER. سيضيف الاستعلام أدناه معرف الشخص كعمود هوية في جدول الشخص:
ALTER TABLE person ADD PersonID INT IDENTITY(10,1) PRIMARY KEY NOT NULL;
إضافة قيمة إلى عمود الهوية بشكل صريح
إذا أضفنا صفًا جديدًا إلى الجدول أعلاه عن طريق تحديد قيمة عمود الهوية بشكل صريح، فسيقوم SQL Server بإلقاء خطأ. انظر الاستعلام أدناه:
INSERT INTO person(Fullname, Occupation, Gender, PersonID) VALUES('Mary Smith', 'Business Analyst', 'Female', 13);
سيتم تنفيذ هذا الاستعلام من خلال الخطأ التالي:
لإدراج قيمة عمود الهوية بشكل صريح، نحتاج أولاً إلى تعيين قيمة IDENTITY_INSERT ON. بعد ذلك، قم بتنفيذ عملية الإدراج لإضافة صف جديد إلى الجدول ثم قم بتعيين قيمة IDENTITY_INSERT OFF. انظر البرنامج النصي للكود أدناه:
SET IDENTITY_INSERT person ON /*INSERT VALUE*/ INSERT INTO person(Fullname, Occupation, Gender, PersonID) VALUES('Mary Smith', 'Business Analyst', 'Female', 14); SET IDENTITY_INSERT person OFF SELECT * FROM person;
IDENTITY_INSERT قيد التشغيل يتيح للمستخدمين وضع البيانات في أعمدة الهوية، بينما IDENTITY_INSERT OFF يمنعهم من إضافة قيمة إلى هذا العمود.
سيؤدي تنفيذ البرنامج النصي للكود إلى عرض الإخراج أدناه حيث يمكننا أن نرى أنه تم إدراج معرف الشخص ذو القيمة 14 بنجاح.
تطابق وظيفي
يوفر SQL Server بعض وظائف الهوية للعمل مع أعمدة IDENTITY في الجدول. وظائف الهوية هذه مذكورة أدناه:
- @@تطابق وظيفي
- وظيفة SCOPE_IDENTITY()
- وظيفة IDENT_CURRENT
- تطابق وظيفي
دعونا نلقي نظرة على وظائف IDENTITY مع بعض الأمثلة.
@@تطابق وظيفي
@@IDENTITY هي وظيفة معرفة من قبل النظام يعرض قيمة الهوية الأخيرة (الحد الأقصى لقيمة الهوية المستخدمة) التي تم إنشاؤها في جدول لعمود IDENTITY في نفس الجلسة. يقوم عمود الدالة هذا بإرجاع قيمة الهوية التي تم إنشاؤها بواسطة العبارة بعد إدراج إدخال جديد في الجدول. يعود أ باطل القيمة عندما نقوم بتنفيذ استعلام لا ينشئ قيم IDENTITY. إنه يعمل دائمًا ضمن نطاق الجلسة الحالية. لا يمكن استخدامه عن بعد.
مثال
لنفترض أن الحد الأقصى الحالي لقيمة الهوية في جدول الأشخاص هو 13. الآن سنضيف سجلًا واحدًا في نفس الجلسة يزيد من قيمة الهوية بمقدار واحد. ثم سنستخدم الدالة @@IDENTITY للحصول على آخر قيمة هوية تم إنشاؤها في نفس الجلسة.
هنا هو البرنامج النصي للكود الكامل:
SELECT MAX(PersonID) AS maxidentity FROM person; INSERT INTO person(Fullname, Occupation, Gender) VALUES('Brian Lara', 'Cricket', 'Male'); SELECT @@IDENTITY;
سيؤدي تنفيذ البرنامج النصي إلى إرجاع الإخراج التالي حيث يمكننا أن نرى الحد الأقصى لقيمة الهوية المستخدمة هو 14.
وظيفة SCOPE_IDENTITY()
SCOPE_IDENTITY() هي وظيفة محددة من قبل النظام عرض أحدث قيمة هوية في جدول ضمن النطاق الحالي. يمكن أن يكون هذا النطاق وحدة نمطية، أو مشغلًا، أو وظيفة، أو إجراءً مخزنًا. وهي تشبه الدالة @@IDENTITY()، باستثناء أن هذه الدالة لها نطاق محدود فقط. ترجع الدالة SCOPE_IDENTITY NULL إذا قمنا بتنفيذها قبل عملية الإدراج التي تولد قيمة في نفس النطاق.
مثال
يستخدم الكود أدناه كلاً من الدالة @@IDENTITY وSCOPE_IDENTITY() في نفس الجلسة. سيعرض هذا المثال أولاً قيمة الهوية الأخيرة، ثم يقوم بإدراج صف واحد في الجدول. بعد ذلك، يقوم بتنفيذ كلتا وظيفتي الهوية.
SELECT MAX(PersonID) AS maxid FROM person; INSERT INTO person(Fullname, Occupation, Gender) VALUES('Jennifer Winset', 'Actoress', 'Female'); SELECT SCOPE_IDENTITY(); SELECT @@IDENTITY;
سيؤدي تنفيذ التعليمات البرمجية إلى عرض نفس القيمة في الجلسة الحالية ونطاق مماثل. انظر صورة الإخراج أدناه:
الآن سنرى كيف تختلف كلتا الوظيفتين بمثال. أولاً، سنقوم بإنشاء جدولين بأسمائهما بيانات الموظف و قسم باستخدام العبارة أدناه:
CREATE TABLE employee_data ( emp_id INT IDENTITY(1, 1) PRIMARY KEY NOT NULL, fullname VARCHAR(20) NULL ) GO CREATE TABLE department ( department_id INT IDENTITY(100, 5) PRIMARY KEY, department_name VARCHAR(20) NULL );
بعد ذلك، نقوم بإنشاء مشغل INSERT في جدول بيانات_الموظف. يتم استدعاء هذا المشغل لإدراج صف في جدول القسم عندما نقوم بإدراج صف في جدول بيانات_الموظف.
يقوم الاستعلام أدناه بإنشاء مشغل لإدراج قيمة افتراضية 'هو - هي' في جدول القسم في كل استعلام إدراج في جدول بيانات_الموظف:
الأرقام في الأبجدية
CREATE TRIGGER Insert_Department ON employee_data FOR INSERT AS BEGIN INSERT INTO department VALUES ('IT') END;
بعد إنشاء المشغل، سنقوم بإدراج سجل واحد في جدول بيانات الموظف ونرى مخرجات كل من الدالتين @@IDENTITY وSCOPE_IDENTITY().
INSERT INTO employee_data VALUES ('John Mathew');
سيؤدي تنفيذ الاستعلام إلى إضافة صف واحد إلى جدول بيانات_الموظف وإنشاء قيمة هوية في نفس الجلسة. بمجرد تنفيذ استعلام الإدراج في جدول بيانات_الموظف، فإنه يقوم تلقائيًا باستدعاء مشغل لإضافة صف واحد في جدول القسم. القيمة الأساسية للهوية هي 1 لبيانات الموظف و100 لجدول القسم.
أخيرًا، نقوم بتنفيذ العبارات التالية التي تعرض الإخراج 100 لوظيفة SELECT @@IDENTITY و1 لوظيفة SCOPE_IDENTITY لأنها تُرجع قيمة الهوية في نفس النطاق فقط.
SELECT MAX(emp_id) FROM employee_data SELECT MAX(department_id) FROM department SELECT @@IDENTITY SELECT SCOPE_IDENTITY()
وهنا النتيجة:
وظيفة IDENT_CURRENT()
IDENT_CURRENT هي وظيفة محددة من قبل النظام عرض أحدث قيمة IDENTITY تم إنشاؤها لجدول معين تحت أي اتصال. لا تأخذ هذه الوظيفة في الاعتبار نطاق استعلام SQL الذي يقوم بإنشاء قيمة الهوية. تتطلب هذه الوظيفة اسم الجدول الذي نريد الحصول على قيمة الهوية له.
مثال
يمكننا فهم ذلك من خلال فتح نافذتي الاتصال أولاً. سنقوم بإدراج سجل واحد في النافذة الأولى التي تولد قيمة الهوية 15 في جدول الشخص. بعد ذلك، يمكننا التحقق من قيمة الهوية هذه في نافذة اتصال أخرى حيث يمكننا رؤية نفس الإخراج. هنا هو الرمز الكامل:
1st Connection Window INSERT INTO person(Fullname, Occupation, Gender) VALUES('John Doe', 'Engineer', 'Male'); GO SELECT MAX(PersonID) AS maxid FROM person; 2nd Connection Window SELECT MAX(PersonID) AS maxid FROM person; GO SELECT IDENT_CURRENT('person') AS identity_value;
سيؤدي تنفيذ الرموز المذكورة أعلاه في نافذتين مختلفتين إلى عرض نفس قيمة الهوية.
تطابق وظيفي
الدالة IDENTITY() هي دالة معرفة من قبل النظام يستخدم لإدراج عمود الهوية في جدول جديد . تختلف هذه الوظيفة عن خاصية IDENTITY التي نستخدمها مع عبارات CREATE TABLE وALTER TABLE. يمكننا استخدام هذه الوظيفة فقط في عبارة SELECT INTO، والتي يتم استخدامها أثناء نقل البيانات من جدول إلى آخر.
يوضح بناء الجملة التالي استخدام هذه الوظيفة في SQL Server:
IDENTITY (data_type , seed , increment) AS column_name
إذا كان الجدول المصدر يحتوي على عمود هوية، فإن الجدول الذي تم تكوينه باستخدام أمر SELECT INTO يرثه افتراضيًا. على سبيل المثال لقد قمنا مسبقًا بإنشاء شخص جدول بعمود هوية. لنفترض أننا قمنا بإنشاء جدول جديد يرث جدول الشخص باستخدام عبارات SELECT INTO مع الدالة IDENTITY(). في هذه الحالة، سوف نحصل على خطأ لأن الجدول المصدر يحتوي بالفعل على عمود هوية. انظر الاستعلام أدناه:
SELECT IDENTITY(INT, 100, 2) AS NEW_ID, PersonID, Fullname, Occupation, Gender INTO person_info FROM person;
سيؤدي تنفيذ البيان أعلاه إلى إرجاع رسالة الخطأ التالية:
لنقم بإنشاء جدول جديد بدون خاصية الهوية باستخدام العبارة التالية:
CREATE TABLE student_data ( roll_no INT PRIMARY KEY NOT NULL, fullname VARCHAR(20) NULL )
ثم انسخ هذا الجدول باستخدام عبارة SELECT INTO بما في ذلك وظيفة IDENTITY كما يلي:
SELECT IDENTITY(INT, 100, 1) AS student_id, roll_no, fullname INTO temp_data FROM student_data;
بمجرد تنفيذ البيان، يمكننا التحقق من ذلك باستخدام sp_help الأمر الذي يعرض خصائص الجدول.
يمكنك رؤية عمود الهوية في مغرية خصائص وفقا للشروط المحددة.
إذا استخدمنا هذه الوظيفة مع عبارة SELECT، فسوف يرسل SQL Server رسالة الخطأ التالية:
Msg 177، Level 15، State 1، Line 2 لا يمكن استخدام وظيفة IDENTITY إلا عندما تحتوي عبارة SELECT على عبارة INTO.
إعادة استخدام قيم IDENTITY
لا يمكننا إعادة استخدام قيم الهوية في جدول SQL Server. عندما نقوم بحذف أي صف من جدول عمود الهوية، سيتم إنشاء فجوة في عمود الهوية. أيضًا، سيقوم SQL Server بإنشاء فجوة عندما نقوم بإدراج صف جديد في عمود الهوية، ويفشل البيان أو يتم التراجع عنه. تشير الفجوة إلى فقدان قيم الهوية ولا يمكن إنشاؤها مرة أخرى في عمود الهوية.
خذ بعين الاعتبار المثال أدناه لفهمه عمليا. لدينا بالفعل جدول شخص يحتوي على البيانات التالية:
بعد ذلك، سنقوم بإنشاء جدولين آخرين بالاسم 'موضع' ، و ' person_position 'باستخدام العبارة التالية:
CREATE TABLE POSITION ( PositionID INT IDENTITY (1, 1) PRIMARY KEY, Position_name VARCHAR (255) NOT NULL ); CREATE TABLE person_position ( PersonID INT, PositionID INT, PRIMARY KEY (PersonID, PositionID), FOREIGN KEY (PersonID) REFERENCES person (PersonID), FOREIGN KEY (PositionID) REFERENCES POSITION (PositionID) );
بعد ذلك، نحاول إدراج سجل جديد في جدول الأشخاص وتعيين موضع لهم عن طريق إضافة صف جديد في جدول person_position. سنفعل ذلك باستخدام بيان المعاملة على النحو التالي:
BEGIN TRANSACTION BEGIN TRY -- insert a new row into the person table INSERT INTO person (Fullname, Occupation, Gender) VALUES('Joan Smith', 'Manager', 'Male'); -- assign a position to a new person INSERT INTO person_position (PersonID, PositionID) VALUES(@@IDENTITY, 10); END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; END CATCH IF @@TRANCOUNT > 0 COMMIT TRANSACTION;
ينفذ البرنامج النصي لرمز المعاملة أعلاه بيان الإدراج الأول بنجاح. لكن البيان الثاني فشل لأنه لم يكن هناك موضع بالمعرف العاشر في جدول الموضع. وبالتالي، تم التراجع عن الصفقة بأكملها.
نظرًا لأن الحد الأقصى لقيمة الهوية في عمود PersonID هو 16، فقد استهلكت عبارة الإدراج الأولى قيمة الهوية 17، ثم تم التراجع عن المعاملة. لذلك، إذا قمنا بإدراج الصف التالي في جدول الأشخاص، فستكون قيمة الهوية التالية 18. قم بتنفيذ العبارة التالية:
INSERT INTO person(Fullname, Occupation, Gender) VALUES('Peter Drucker',' Writer', 'Female');
بعد التحقق من جدول الشخص مرة أخرى، نرى أن السجل المضاف حديثًا يحتوي على قيمة الهوية 18.
عمودين IDENTITY في جدول واحد
من الناحية الفنية، ليس من الممكن إنشاء عمودين للهوية في جدول واحد. إذا فعلنا ذلك، فسيقوم SQL Server بإلقاء خطأ. راجع الاستعلام التالي:
CREATE TABLE TwoIdentityTable ( ID1 INT IDENTITY (10, 1) NOT NULL, ID2 INT IDENTITY (100, 1) NOT NULL )
عندما نقوم بتنفيذ هذا الكود سنرى الخطأ التالي:
ومع ذلك، يمكننا إنشاء عمودين للهوية في جدول واحد باستخدام العمود المحسوب. يقوم الاستعلام التالي بإنشاء جدول يحتوي على عمود محسوب يستخدم عمود الهوية الأصلي ويقلله بمقدار 1.
CREATE TABLE TwoIdentityTable ( ID1 INT IDENTITY (10, 1) NOT NULL, SecondID AS 10000-ID1, Descriptions VARCHAR(60) )
بعد ذلك، سنضيف بعض البيانات إلى هذا الجدول باستخدام الأمر أدناه:
INSERT INTO TwoIdentityTable (Descriptions) VALUES ('Javatpoint provides best educational tutorials'), ('www.javatpoint.com')
وأخيرًا، نتحقق من بيانات الجدول باستخدام عبارة SELECT. يقوم بإرجاع الإخراج التالي:
يمكننا أن نرى في الصورة كيف يعمل عمود SecondID كعمود هوية ثانٍ، متناقصًا بمقدار عشرة عن القيمة الأولية البالغة 9990.
المفاهيم الخاطئة لعمود هوية SQL Server
لدى مستخدم DBA العديد من المفاهيم الخاطئة فيما يتعلق بأعمدة هوية SQL Server. فيما يلي قائمة بالمفاهيم الخاطئة الأكثر شيوعًا فيما يتعلق بأعمدة الهوية التي يمكن رؤيتها:
عمود الهوية فريد من نوعه: وفقًا للوثائق الرسمية لـ SQL Server، لا يمكن لخاصية الهوية ضمان أن تكون قيمة العمود فريدة. يجب أن نستخدم مفتاحًا أساسيًا أو قيدًا فريدًا أو فهرسًا فريدًا لفرض تفرد العمود.
يقوم عمود IDENTITY بإنشاء أرقام متتالية: تنص الوثائق الرسمية بوضوح على أنه يمكن فقدان القيم المخصصة في عمود الهوية عند فشل قاعدة البيانات أو إعادة تشغيل الخادم. يمكن أن يسبب فجوات في قيمة الهوية أثناء الإدراج. يمكن أيضًا إنشاء الفجوة عندما نحذف القيمة من الجدول، أو يتم التراجع عن عبارة الإدراج. ولا يمكن استخدام القيم التي تولد الفجوات بشكل أكبر.
لا يمكن لعمود IDENTITY إنشاء القيم الموجودة تلقائيًا: ليس من الممكن لعمود الهوية إنشاء القيم الموجودة تلقائيًا حتى تتم إعادة زرع خاصية الهوية باستخدام الأمر DBCC CHECKIDENT. يسمح لنا بضبط القيمة الأولية (قيمة البداية للصف) لخاصية الهوية. بعد تنفيذ هذا الأمر، لن يقوم SQL Server بالتحقق من القيم التي تم إنشاؤها حديثًا والموجودة بالفعل في الجدول أم لا.
عمود الهوية كمفتاح أساسي يكفي لتحديد الصف: إذا كان المفتاح الأساسي يحتوي على عمود الهوية في الجدول دون أي قيود فريدة أخرى، فيمكن للعمود تخزين قيم مكررة ومنع تفرد العمود. كما نعلم، لا يمكن للمفتاح الأساسي تخزين القيم المكررة، ولكن يمكن لعمود الهوية تخزين التكرارات؛ يوصى بعدم استخدام المفتاح الأساسي وخاصية الهوية في نفس العمود.
استخدام الأداة الخاطئة لاستعادة قيم الهوية بعد الإدراج: من المفاهيم الخاطئة الشائعة أيضًا عدم الوعي بالاختلافات بين وظائف @@IDENTITY وSCOPE_IDENTITY() وIDENT_CURRENT وIDENTITY() للحصول على قيمة الهوية المُدرجة مباشرةً من العبارة التي قمنا بتنفيذها للتو.
الفرق بين التسلسل والهوية
نحن نستخدم كلاً من SEQUENCE وIDENTITY لإنشاء أرقام تلقائية. ومع ذلك، هناك بعض الاختلافات، والفرق الرئيسي هو أن الهوية تعتمد على الجدول، في حين أن التسلسل ليس كذلك. دعونا نلخص اختلافاتهم في شكل جدول:
هوية | تسلسل |
---|---|
يتم استخدام خاصية الهوية لجدول معين ولا يمكن مشاركتها مع جداول أخرى. | يحدد DBA كائن التسلسل الذي يمكن مشاركته بين جداول متعددة لأنه مستقل عن الجدول. |
تقوم هذه الخاصية تلقائيًا بإنشاء قيم في كل مرة يتم فيها تنفيذ عبارة الإدراج على الجدول. | يستخدم جملة NEXT VALUE FOR لإنشاء القيمة التالية لكائن التسلسل. |
لا يقوم SQL Server بإعادة تعيين قيمة عمود خاصية الهوية إلى قيمتها الأولية. | يمكن لـ SQL Server إعادة تعيين قيمة كائن التسلسل. |
لا يمكننا تعيين الحد الأقصى لقيمة خاصية الهوية. | يمكننا تعيين الحد الأقصى لقيمة كائن التسلسل. |
تم تقديمه في SQL Server 2000. | تم تقديمه في SQL Server 2012. |
لا يمكن لهذه الخاصية إنشاء قيمة هوية بترتيب تنازلي. | يمكنه توليد القيم بترتيب تنازلي. |
خاتمة
ستقدم هذه المقالة نظرة عامة كاملة على خاصية IDENTITY في SQL Server. لقد تعلمنا هنا كيف ومتى يتم استخدام خاصية الهوية، ووظائفها المختلفة، والمفاهيم الخاطئة، وكيف تختلف عن التسلسل.