مثالهای عملی از پایه تا حرفهای
ده مثال زیر مستقل طراحی شدهاند. هر نمونه هدف، Query کامل، خروجی مورد انتظار و نکته کاربردی دارد. اشیای آزمایشی را در پایگاه توسعه اجرا کنید و از اجرای کدهای آموزشی روی Production بدون بازبینی مجوز و اثر قفل خودداری نمایید.
مثال 1: خواندن مقدار جدول نمونه
مثال پایه با مقدار یا محیط کنترلشده است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
CREATE TABLE #CurrentDemo(Id int IDENTITY(1,1), Value int);
INSERT #CurrentDemo(Value) VALUES(1),(2);
SELECT IDENT_CURRENT(N'tempdb..#CurrentDemo') AS CurrentId;
DROP TABLE #CurrentDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| 2 یا وابسته به نام داخلی جدول موقت | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 2: استفاده مطمئن با جدول دائمی آزمایشی
نمونه قابل اجرا روی داده آزمایشی است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
DROP TABLE IF EXISTS dbo.IdentityCurrentDemo;
CREATE TABLE dbo.IdentityCurrentDemo(Id int IDENTITY(20,2), Value int);
INSERT dbo.IdentityCurrentDemo(Value) VALUES(1),(2);
SELECT IDENT_CURRENT(N'dbo.IdentityCurrentDemo') AS CurrentId;
DROP TABLE dbo.IdentityCurrentDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| 22 | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 3: مقایسه با SCOPE IDENTITY
کاربرد در SELECT و مشاهده خروجی است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
DROP TABLE IF EXISTS dbo.IdentityCompareDemo;
CREATE TABLE dbo.IdentityCompareDemo(Id int IDENTITY, Value int);
INSERT dbo.IdentityCompareDemo(Value) VALUES(8);
SELECT SCOPE_IDENTITY() AS ScopeId, IDENT_CURRENT(N'dbo.IdentityCompareDemo') AS TableId;
DROP TABLE dbo.IdentityCompareDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| هر دو 1 در یک نشست | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 4: اثر Seed سفارشی
کاربرد در تصمیمگیری یا کنترل جریان است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
DROP TABLE IF EXISTS dbo.IdentitySeedDemo;
CREATE TABLE dbo.IdentitySeedDemo(Id int IDENTITY(100,10), Value int);
INSERT dbo.IdentitySeedDemo(Value) VALUES(1);
SELECT IDENT_CURRENT(N'dbo.IdentitySeedDemo') AS CurrentId;
DROP TABLE dbo.IdentitySeedDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| 100 | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 5: پس از TRUNCATE
ترکیب با قابلیتهای دیگر SQL Server است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
DROP TABLE IF EXISTS dbo.IdentityTruncateDemo;
CREATE TABLE dbo.IdentityTruncateDemo(Id int IDENTITY(5,1), Value int);
INSERT dbo.IdentityTruncateDemo(Value) VALUES(1);
TRUNCATE TABLE dbo.IdentityTruncateDemo;
SELECT IDENT_CURRENT(N'dbo.IdentityTruncateDemo') AS CurrentAfterTruncate;
DROP TABLE dbo.IdentityTruncateDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| مقدار Seed یعنی 5 | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 6: نام شیء نامعتبر
بررسی مقدار تهی یا وضعیت بدون داده است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
SELECT IDENT_CURRENT(N'dbo.TableThatDoesNotExist') AS InvalidObject;
| خروجی مورد انتظار | تفسیر |
|---|
| NULL | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 7: تبدیل نوع خروجی
رفتار مرزی و شرایط غیرمعمول است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
SELECT CONVERT(bigint, IDENT_CURRENT(N'sys.objects')) AS MetadataValue;
| خروجی مورد انتظار | تفسیر |
|---|
| عدد یا NULL وابسته به شیء | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 8: گزارش Metadata چند جدول
سناریوی واقعی پایش یا گزارشگیری سازمانی است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
SELECT t.name, IDENT_CURRENT(QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.name)) AS CurrentIdentity
FROM sys.tables AS t
WHERE OBJECTPROPERTY(t.object_id, 'TableHasIdentity') = 1;
| خروجی مورد انتظار | تفسیر |
|---|
| فهرست جدولهای Identity | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 9: روش ناامن پیشبینی شناسه
روش اشتباه و نسخه اصلاحشده است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
DROP TABLE IF EXISTS dbo.IdentityRaceDemo;
CREATE TABLE dbo.IdentityRaceDemo(Id int IDENTITY, Value int);
SELECT IDENT_CURRENT(N'dbo.IdentityRaceDemo') + IDENT_INCR(N'dbo.IdentityRaceDemo') AS PredictedButUnsafe;
INSERT dbo.IdentityRaceDemo(Value) OUTPUT inserted.Id VALUES(1);
DROP TABLE dbo.IdentityRaceDemo;
| خروجی مورد انتظار | تفسیر |
|---|
| OUTPUT شناسه واقعی را میدهد | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: این نمونه مرز میان روش شکننده و الگوی قابل اتکا را نشان میدهد. به نشست جاری محدود نیست و در سیستم همزمان نباید برای تعیین شناسه ردیفی که همین کاربر درج کرده استفاده شود. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
مثال 10: پایش بدون استفاده تجاری
نکته کارایی، ایمنی یا نگهداشتپذیری است. هدف این است که رفتار IDENT_CURRENT() در یک Batch روشن دیده شود و نتیجه به حدس یا وضعیت اتصال دیگری وابسته نباشد. کد را ابتدا در محیط آزمایشی اجرا کنید و در پروژه واقعی نام اشیا و مجوزها را با استاندارد سازمان هماهنگ سازید.
SELECT s.name AS SchemaName, t.name AS TableName, ic.seed_value, ic.increment_value, ic.last_value
FROM sys.identity_columns AS ic
JOIN sys.tables AS t ON t.object_id = ic.object_id
JOIN sys.schemas AS s ON s.schema_id = t.schema_id;
| خروجی مورد انتظار | تفسیر |
|---|
| گزارش مشخصات Identity | نتیجه، رفتار IDENT_CURRENT() را در همین سناریو نشان میدهد. |
نکته کاربردی: پس از اجرای دستور، خروجی را در همان Scope و نشست تفسیر کنید. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. در سامانه پرترافیک، ثبت زمان، نام پایگاه داده و شناسه نشست کنار نتیجه میتواند عیبیابی را سریعتر کند.
سؤالات متداول
پرسش 1: IDENT_CURRENT() دقیقاً چه کاری انجام میدهد؟
IDENT_CURRENT() آخرین مقدار Identity تولیدشده برای یک جدول مشخص را مستقل از نشست و Scope گزارش میکند. خروجی باید در متن همان Batch و با توجه به Scope، Session و دستور قبلی تفسیر شود؛ جدا کردن آن از زمینه اجرا میتواند نتیجهای ظاهراً درست اما از نظر تجاری اشتباه بسازد.
پرسش 2: بهترین زمان خواندن IDENT_CURRENT() چه موقع است؟
بهترین زمان بلافاصله پس از دستور مرتبط است. اگر مقدار برای چند مرحله بعد لازم است، آن را در متغیری با نوع مناسب ذخیره کنید و همراه شناسه عملیات ثبت نمایید تا دستورهای واسط مقدار یا معنای آن را تغییر ندهند.
پرسش 3: آیا IDENT_CURRENT() برای سامانههای سازمانی مناسب است؟
بله، مشروط بر اینکه قرارداد استفاده، مدیریت خطا و تست همزمانی مشخص باشد. در طراحی حرفهای، این تابع بخشی از راهحل است و در کنار Transaction، Logging، مجوز حداقلی و پایش Query به کار میرود.
پرسش 4: برای پیادهسازی صحیح آن به مشاوره SQL Server نیاز است؟
در کد ساده خیر، اما در سامانههای مالی، انبار، احراز هویت یا پردازش گروهی بررسی Triggerها، Scopeها و الگوی تراکنش اهمیت زیادی دارد. بازبینی تخصصی میتواند از خطاهای خاموش و هزینه اصلاح داده جلوگیری کند.
پرسش 5: تفاوت IDENT_CURRENT() با گزینههای نزدیک چیست؟
تفاوت اصلی در دامنه مشاهده و نوع اطلاعات است. باید مشخص شود نیاز شما مربوط به آخرین Statement، نشست جاری، Scope جاری، جدول مشخص یا Metadata سرور است؛ سپس تابعی انتخاب شود که دقیقاً همان مرز را پوشش دهد.
پرسش 6: آیا میتوان این الگو را در Stored Procedure پروژه پیاده کرد؟
بله. بهتر است مقدار در همان Procedure گرفته شود، نوع خروجی صریح باشد، خطا با TRY...CATCH مدیریت شود و نتیجه از طریق Result Set، پارامتر OUTPUT یا قرارداد سرویس بازگردد. تست یکپارچه نیز حالت موفق و شکست را پوشش دهد.
پرسش 7: خطای رایج هنگام استفاده از IDENT_CURRENT() چیست؟
استفاده برای بازیابی شناسه درج خود کاربر یکی از خطاهای متداول است. خطای دیگر، اتکا به نتیجه بدون ثبت Context اجراست. نسخه اصلاحشده باید زمان خواندن، Scope، رفتار تراکنش و نوع تبدیل را آشکار کند.
پرسش 8: اثر IDENT_CURRENT() بر Performance چیست؟
خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست. هزینه اصلی معمولاً از Query یا Transaction پیرامون آن میآید، نه خود تابع. اندازهگیری با Actual Execution Plan، Query Store و Extended Events باید روی کل جریان انجام شود.
پرسش 9: Best Practice اصلی برای IDENT_CURRENT() چیست؟
مقدار را نزدیک به دستور مرجع بخوانید، در نوع مناسب ذخیره کنید، نتیجههای مرزی مانند صفر یا NULL را تست کنید و برای عملیات حساس گزارش ممیزی بسازید. از تکیه بر ترتیب اتفاقی دستورات یا رشتههای Hard-coded دوری کنید.
پرسش 10: این قابلیت در کدام نسخههای SQL Server کار میکند؟
این قابلیت در نسخههای رایج و پشتیبانیشده SQL Server در دسترس است، اما امکانات مکمل مانند SESSION_CONTEXT، THROW یا برخی DMVها به نسخه و سطح سازگاری وابستهاند. پیش از استقرار، مستندات همان نسخه و Compatibility Level پایگاه داده را کنترل کنید.
سؤالات مصاحبه SQL Server
سؤال 1: مرز مشاهده IDENT_CURRENT() چیست؟
پاسخ حرفهای باید مشخص کند تابع به Statement، Scope، Session، Table یا Server مربوط است و یک مثال نقض نیز ارائه دهد. گفتن نام تابع بدون توضیح مرز مشاهده برای مصاحبه فنی کافی نیست.
سؤال 2: چگونه مقدار را بدون Race Condition مصرف میکنید؟
مقدار باید نزدیک به عملیات مرجع، در همان اتصال و داخل قرارداد تراکنش خوانده شود. برای چند ردیف یا خروجیهای حساس، قابلیت OUTPUT یا Metadata ساختیافته میتواند انتخاب دقیقتری باشد.
سؤال 3: در CATCH چه اطلاعاتی ثبت میکنید؟
شماره و متن خطا، Procedure، Line، XACT_STATE، @@TRANCOUNT، نام پایگاه داده، SPID و شناسه همبستگی از اطلاعات مفید هستند. داده حساس نباید بدون پالایش وارد Log شود.
سؤال 4: چطور این کد را تست میکنید؟
تست موفق، نتیجه خالی، خطا، تراکنش باز، اجرای همزمان و وجود Trigger یا دستور واسط باید جداگانه پوشش داده شود. تست باید مقدار خروجی و وضعیت نهایی داده را هر دو بررسی کند.
سؤال 5: چه زمانی گزینه دیگری را انتخاب میکنید؟
وقتی تابع مرز موردنیاز را پوشش نمیدهد یا فقط یک مقدار از مجموعهای بزرگ را برمیگرداند. انتخاب باید بر اساس هدف تجاری، همزمانی، نسخه SQL Server و قابلیت مشاهدهپذیری انجام شود.