راهنمای جامع توابع سیستمی SQL Server؛ وضعیت اجرا، Identity، تراکنش و نشست
مقدمه
توابع سیستمی SQL Server پلی میان Query و وضعیت داخلی موتور هستند. با آنها میتوان فهمید آخرین دستور چند ردیف را پردازش کرده، چه خطایی رخ داده، آخرین Identity در کدام مرز ساخته شده، چند سطح تراکنش باز است و اتصال روی چه سرور و نشستی اجرا میشود.
سادگی Syntax گاهی گمراهکننده است. بخش دشوار، انتخاب تابع درست و خواندن مقدار در زمان مناسب است. تفاوت Session، Scope و Object در محیط تککاربره کوچک دیده نمیشود، اما زیر بار همزمان، با Trigger یا در Procedureهای تودرتو میتواند به خطای داده منجر شود.
این راهنما نه تابع و متغیر سیستمی را در چهار خانواده منطقی آموزش میدهد. برای هر مورد مقالهای مستقل با ده مثال عملی، خروجی نمونه، خطاهای رایج، Performance، Best Practice، FAQ و سؤال مصاحبه آماده شده است.
پیش از اجرای نمونهها روی سرور واقعی، آنها را در پایگاه توسعه بررسی کنید. کدهای آموزشی ممکن است جدول آزمایشی بسازند، تراکنش باز کنند یا Metadata محیط را نمایش دهند؛ بنابراین مجوز و اثر جانبی را آگاهانه مدیریت نمایید.
اصل طراحی: ابتدا مشخص کنید سؤال شما درباره Statement، Scope، Session، Table، Transaction یا Server است؛ سپس تابعی را انتخاب کنید که دقیقاً همان مرز را پوشش دهد.
مدل ذهنی درست برای توابع سیستمی
Statement کوچکترین واحد موردنظر در این مجموعه است. @@ROWCOUNT و @@ERROR به آخرین دستور وابستهاند، پس یک SELECT تشخیصی یا SET میتواند مقدار مورد انتظار را تغییر دهد. ذخیره فوری در متغیر، قرارداد را شفاف و تست را تکرارپذیر میکند.
Scope محدودهای مانند Batch، Stored Procedure یا Trigger است. SCOPE_IDENTITY مقدار ساختهشده در Scope فعلی را میبیند، در حالی که @@IDENTITY میتواند مقدار ساختهشده در Trigger همان Session را نیز برگرداند. IDENT_CURRENT از این دو جداست و به جدول نگاه میکند، حتی اگر درج در نشست دیگری انجام شده باشد.
Transaction به اتصال وابسته است. BEGIN TRANSACTION شمارنده را افزایش میدهد، COMMIT یک سطح کم میکند و ROLLBACK بدون Savepoint کل تراکنش را برمیگرداند. @@TRANCOUNT فقط تعداد را میدهد؛ برای قابل Commit بودن تراکنش باید XACT_STATE نیز بررسی شود.
Server و Session لایه مشاهدهپذیری هستند. @@SERVERNAME نام پیکربندیشده، @@VERSION متن نسخه و @@SPID شناسه نشست را ارائه میکنند. این دادهها برای Audit و پشتیبانی مفیدند، اما SPID قابل استفاده مجدد است و متن نسخه برای منطق ساختیافته مناسب نیست.
دستهبندی منطقی
وضعیت اجرای دستور
@@ROWCOUNT و @@ERROR نتیجه آخرین Statement را از نظر تعداد ردیف و شماره خطا گزارش میکنند. ترتیب خواندن این مقادیر حیاتی است و هر دستور واسط میتواند Context را عوض کند.
مدیریت Identity
@@IDENTITY، SCOPE_IDENTITY و IDENT_CURRENT سه مرز متفاوت دارند: نشست، Scope و جدول. انتخاب نادرست در حضور Trigger یا همزمانی میتواند شناسه ردیف دیگری را به برنامه تحویل دهد.
کنترل تراکنش
@@TRANCOUNT تعداد سطحهای باز در اتصال جاری را نشان میدهد. این مقدار همراه XACT_STATE و TRY...CATCH برای طراحی Procedureهای قابل ترکیب اهمیت دارد.
اطلاعات سرور و نشست
@@SERVERNAME، @@VERSION و @@SPID برای Inventory، عیبیابی اتصال و همبستهسازی رخدادها استفاده میشوند. این مقادیر نباید بدون پالایش در خروجی عمومی افشا شوند.
جدول مقایسه توابع
| تابع | کاربرد اصلی | نوع خروجی یا نکته مهم | لینک آموزش کامل |
|---|
| @@ROWCOUNT | تعداد ردیفهایی را برمیگرداند که آخرین دستور اجراشده در همان اتصال خوانده یا تغییر داده است | int؛ هر دستور بعدی میتواند مقدار آن را عوض کند؛ بنابراین باید بلافاصله در یک متغیر محلی ذخیره شود | آموزش @@ROWCOUNT |
| @@ERROR | شماره خطای آخرین دستور Transact-SQL را در همان اتصال گزارش میکند و در صورت نبود خطا مقدار صفر میدهد | int؛ مقدار فقط برای دستور بلافاصله قبل معتبر است و برای کدهای جدید، TRY...CATCH و ERROR_NUMBER معمولاً انتخاب خواناتر و مطمئنتری هستند | آموزش @@ERROR |
| @@IDENTITY | آخرین مقدار Identity تولیدشده در کل نشست جاری را بدون محدودیت Scope برمیگرداند | numeric(38,0)؛ Trigger میتواند مقدار آن را تغییر دهد؛ برای دریافت شناسه همان Scope معمولاً SCOPE_IDENTITY انتخاب امنتری است | آموزش @@IDENTITY |
| SCOPE_IDENTITY() | آخرین مقدار Identity ساختهشده در Scope و نشست جاری را برمیگرداند و اثر Scope داخلی Trigger را جدا میکند | numeric(38,0)؛ برای درج چندردیفی فقط آخرین مقدار را میدهد؛ در آن حالت OUTPUT inserted.Id راهحل کاملتری است | آموزش SCOPE_IDENTITY() |
| IDENT_CURRENT() | آخرین مقدار Identity تولیدشده برای یک جدول مشخص را مستقل از نشست و Scope گزارش میکند | numeric(38,0)؛ به نشست جاری محدود نیست و در سیستم همزمان نباید برای تعیین شناسه ردیفی که همین کاربر درج کرده استفاده شود | آموزش IDENT_CURRENT() |
| @@TRANCOUNT | سطح تراکنشهای فعال در اتصال جاری را نشان میدهد و برای کنترل BEGIN، COMMIT و ROLLBACK به کار میرود | int؛ تراکنش تودرتو در SQL Server تراکنش مستقل واقعی نیست؛ ROLLBACK بدون Savepoint کل تراکنش را برمیگرداند | آموزش @@TRANCOUNT |
| @@SERVERNAME | نام محلی پیکربندیشده برای نمونه SQL Server را برمیگرداند و ممکن است نام Instance را نیز شامل شود | nvarchar؛ پس از تغییر نام ماشین ممکن است تا اصلاح Metadata و Restart با نام واقعی میزبان متفاوت باشد؛ برای سناریوهای دقیق SERVERPROPERTY را هم بررسی کنید | آموزش @@SERVERNAME |
| @@VERSION | رشتهای توصیفی از نسخه موتور SQL Server، شماره Build، ویرایش و اطلاعات سیستمعامل میزبان ارائه میکند | nvarchar؛ ساختار رشته برای منطق برنامه تضمین مناسبی ندارد؛ برای مقادیر قابل پردازش از SERVERPROPERTY استفاده کنید | آموزش @@VERSION |
| @@SPID | شناسه عددی نشست یا Server Process ID اتصال جاری را نمایش میدهد و برای عیبیابی Blocking و ردیابی درخواستها مفید است | smallint؛ SPID پس از پایان اتصال قابل استفاده مجدد است؛ بنابراین بهتنهایی شناسه دائمی کاربر یا رویداد محسوب نمیشود | آموزش @@SPID |
معرفی تفصیلی هر تابع
@@ROWCOUNT: تعداد ردیفهای پردازششده
@@ROWCOUNT تعداد ردیفهایی را برمیگرداند که آخرین دستور اجراشده در همان اتصال خوانده یا تغییر داده است. نوع خروجی int است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
هر دستور بعدی میتواند مقدار آن را عوض کند؛ بنابراین باید بلافاصله در یک متغیر محلی ذخیره شود. برای تشخیص موفقیت عملیات گروهی مفید است، اما جای طراحی شرط SARGable، بررسی Execution Plan یا شمارش تجاری دقیق را نمیگیرد.
مطالعه مقاله کامل @@ROWCOUNT با ده مثال اجرایی
@@ERROR: کد خطای آخرین دستور
@@ERROR شماره خطای آخرین دستور Transact-SQL را در همان اتصال گزارش میکند و در صورت نبود خطا مقدار صفر میدهد. نوع خروجی int است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
مقدار فقط برای دستور بلافاصله قبل معتبر است و برای کدهای جدید، TRY...CATCH و ERROR_NUMBER معمولاً انتخاب خواناتر و مطمئنتری هستند. هزینه محاسباتی ناچیزی دارد، اما کنترل خطای ردیفبهردیف میتواند جریان برنامه را پیچیده و عملیات را کند کند.
مطالعه مقاله کامل @@ERROR با ده مثال اجرایی
@@IDENTITY: آخرین مقدار Identity نشست
@@IDENTITY آخرین مقدار Identity تولیدشده در کل نشست جاری را بدون محدودیت Scope برمیگرداند. نوع خروجی numeric(38,0) است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
Trigger میتواند مقدار آن را تغییر دهد؛ برای دریافت شناسه همان Scope معمولاً SCOPE_IDENTITY انتخاب امنتری است. خواندن آن سبک است، اما اتکا به مقدار مبهم در زنجیره Triggerها میتواند خطاهای دادهای پرهزینه ایجاد کند.
مطالعه مقاله کامل @@IDENTITY با ده مثال اجرایی
SCOPE_IDENTITY(): آخرین Identity در Scope جاری
SCOPE_IDENTITY() آخرین مقدار Identity ساختهشده در Scope و نشست جاری را برمیگرداند و اثر Scope داخلی Trigger را جدا میکند. نوع خروجی numeric(38,0) است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
برای درج چندردیفی فقط آخرین مقدار را میدهد؛ در آن حالت OUTPUT inserted.Id راهحل کاملتری است. تابعی بسیار سبک است و استفاده درست آن از Query اضافه برای یافتن MAX(Id) و رقابت همزمان جلوگیری میکند.
مطالعه مقاله کامل SCOPE_IDENTITY() با ده مثال اجرایی
IDENT_CURRENT(): آخرین Identity یک جدول
IDENT_CURRENT() آخرین مقدار Identity تولیدشده برای یک جدول مشخص را مستقل از نشست و Scope گزارش میکند. نوع خروجی numeric(38,0) است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
به نشست جاری محدود نیست و در سیستم همزمان نباید برای تعیین شناسه ردیفی که همین کاربر درج کرده استفاده شود. خواندن Metadata سبک است، ولی استفاده مکرر برای پیشبینی شناسه بعدی هم ناامن و هم مستعد رقابت میان نشستهاست.
مطالعه مقاله کامل IDENT_CURRENT() با ده مثال اجرایی
@@TRANCOUNT: تعداد تراکنشهای باز
@@TRANCOUNT سطح تراکنشهای فعال در اتصال جاری را نشان میدهد و برای کنترل BEGIN، COMMIT و ROLLBACK به کار میرود. نوع خروجی int است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
تراکنش تودرتو در SQL Server تراکنش مستقل واقعی نیست؛ ROLLBACK بدون Savepoint کل تراکنش را برمیگرداند. بازماندن تراکنش باعث قفل، رشد Log و Blocking میشود؛ @@TRANCOUNT ابزار تشخیص است و جای مدیریت کوتاه و قطعی تراکنش را نمیگیرد.
مطالعه مقاله کامل @@TRANCOUNT با ده مثال اجرایی
@@SERVERNAME: نام منطقی SQL Server
@@SERVERNAME نام محلی پیکربندیشده برای نمونه SQL Server را برمیگرداند و ممکن است نام Instance را نیز شامل شود. نوع خروجی nvarchar است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
پس از تغییر نام ماشین ممکن است تا اصلاح Metadata و Restart با نام واقعی میزبان متفاوت باشد؛ برای سناریوهای دقیق SERVERPROPERTY را هم بررسی کنید. ثابت سیستمی سبکی است، اما نباید شرطهای پرتکرار تجاری یا مسیر اتصال را بر مبنای رشتهای شکننده طراحی کرد.
مطالعه مقاله کامل @@SERVERNAME با ده مثال اجرایی
@@VERSION: اطلاعات نسخه و سیستمعامل
@@VERSION رشتهای توصیفی از نسخه موتور SQL Server، شماره Build، ویرایش و اطلاعات سیستمعامل میزبان ارائه میکند. نوع خروجی nvarchar است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
ساختار رشته برای منطق برنامه تضمین مناسبی ندارد؛ برای مقادیر قابل پردازش از SERVERPROPERTY استفاده کنید. خواندن گاهبهگاه آن ارزان است، ولی Parse کردن رشته در هر Query کاربردی ضرورتی ندارد و بهتر است Metadata ساختیافته ثبت شود.
مطالعه مقاله کامل @@VERSION با ده مثال اجرایی
@@SPID: شناسه نشست جاری
@@SPID شناسه عددی نشست یا Server Process ID اتصال جاری را نمایش میدهد و برای عیبیابی Blocking و ردیابی درخواستها مفید است. نوع خروجی smallint است و در طراحی لایه داده باید حالتهای مرزی آن نیز پوشش داده شود.
SPID پس از پایان اتصال قابل استفاده مجدد است؛ بنابراین بهتنهایی شناسه دائمی کاربر یا رویداد محسوب نمیشود. خواندن آن بسیار سبک است، اما پایش DMVها باید با فیلتر مناسب و مجوز حداقلی انجام شود تا بار تشخیصی کنترل شود.
مطالعه مقاله کامل @@SPID با ده مثال اجرایی
شش سناریوی ترکیبی و اجرایی
مثال 1: ثبت نتیجه یک SELECT
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
SELECT TOP (3) name FROM sys.objects ORDER BY object_id;
DECLARE @Rows int = @@ROWCOUNT, @Err int = @@ERROR;
SELECT @Rows AS RowsReturned, @Err AS ErrorNumber;
| خروجی مورد انتظار | تحلیل |
|---|
| تعداد 3 و خطای 0 | این الگو نشان میدهد مقدارهای وابسته به Statement باید بلافاصله گرفته شوند. |
این الگو نشان میدهد مقدارهای وابسته به Statement باید بلافاصله گرفته شوند. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
مثال 2: دریافت امن Identity
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
CREATE TABLE #MainGuideId(Id int IDENTITY, Title nvarchar(30));
INSERT #MainGuideId(Title) VALUES(N'نمونه');
SELECT CONVERT(int,SCOPE_IDENTITY()) AS NewId;
DROP TABLE #MainGuideId;
| خروجی مورد انتظار | تحلیل |
|---|
| شناسه 1 | SCOPE_IDENTITY برای شناسه همان Scope از @@IDENTITY دقیقتر است. |
SCOPE_IDENTITY برای شناسه همان Scope از @@IDENTITY دقیقتر است. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
مثال 3: مقایسه سه تابع Identity
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
DROP TABLE IF EXISTS dbo.MainIdentityGuide;
CREATE TABLE dbo.MainIdentityGuide(Id int IDENTITY(10,1), Value int);
INSERT dbo.MainIdentityGuide(Value) VALUES(1);
SELECT @@IDENTITY AS SessionId, SCOPE_IDENTITY() AS ScopeId, IDENT_CURRENT(N'dbo.MainIdentityGuide') AS TableId;
DROP TABLE dbo.MainIdentityGuide;
| خروجی مورد انتظار | تحلیل |
|---|
| هر سه 10 در این مثال | تساوی در مثال ساده نباید تفاوت دامنه سه تابع را پنهان کند. |
تساوی در مثال ساده نباید تفاوت دامنه سه تابع را پنهان کند. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
مثال 4: کنترل تراکنش قابل ترکیب
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
DECLARE @EntryTranCount int = @@TRANCOUNT;
IF @EntryTranCount = 0 BEGIN TRANSACTION;
SELECT @@TRANCOUNT AS DuringWork;
IF @EntryTranCount = 0 COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS AfterWork;
| خروجی مورد انتظار | تحلیل |
|---|
| 1 سپس 0 | Procedure فقط تراکنشی را میبندد که خودش باز کرده است. |
Procedure فقط تراکنشی را میبندد که خودش باز کرده است. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
مثال 5: گزارش محیط اجرا
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
SELECT @@SERVERNAME AS ServerName, @@SPID AS SessionId, DB_NAME() AS DatabaseName, SERVERPROPERTY('ProductVersion') AS ProductVersion;
| خروجی مورد انتظار | تحلیل |
|---|
| مشخصات سرور و نشست | این رکورد برای لاگ استقرار و رخداد عملیاتی مفید است. |
این رکورد برای لاگ استقرار و رخداد عملیاتی مفید است. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
مثال 6: مدیریت خطا با الگوی جدید
این سناریو چند مفهوم را در یک Batch کنترلشده کنار هم قرار میدهد. هدف، مشاهده نتیجه واقعی و ساخت الگویی است که بتوان آن را در Procedure، Job یا لایه سرویس توسعه داد.
BEGIN TRY
BEGIN TRANSACTION;
SELECT 100 / 10 AS Result;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage, @@SPID AS SessionId;
END CATCH;
| خروجی مورد انتظار | تحلیل |
|---|
| Result برابر 10 | TRY...CATCH برای کد جدید از اتکای صرف به @@ERROR خواناتر است. |
TRY...CATCH برای کد جدید از اتکای صرف به @@ERROR خواناتر است. در محیط سازمانی بهتر است شناسه همبستگی، زمان و نام پایگاه نیز ثبت شود تا رخداد میان Log برنامه و SQL Server قابل ردیابی باشد.
طراحی تراکنش و مدیریت خطا
در کد جدید، TRY...CATCH و THROW محور اصلی مدیریت خطا هستند. @@ERROR برای نگهداشت کد قدیمی مفید است، اما چون فقط بلافاصله پس از Statement معتبر است، افزودن یک دستور Logging در جای نامناسب میتواند خطای اصلی را پنهان کند.
در CATCH ابتدا XACT_STATE را بررسی کنید. اگر تراکنش غیرقابل Commit است باید Rollback شود؛ اگر Procedure داخل تراکنش فراخواننده اجرا شده، مالکیت تراکنش و Savepoint را از ابتدا مشخص نمایید. @@TRANCOUNT بهتنهایی سالم بودن تراکنش را ثابت نمیکند.
برای عملیات Idempotent، نتیجه تجاری را با Constraint و کلید یکتا تضمین کنید. تعداد ردیف یا شناسه تولیدشده اطلاعات اجرایی هستند و جای قاعده صحت داده را نمیگیرند. Retry نیز باید محدود، ثبتشده و فقط برای خطاهای گذرا باشد.
همزمانی و انتخاب تابع Identity
پس از INSERT تکردیفی در Scope جاری، SCOPE_IDENTITY معمولاً انتخاب مناسب است. @@IDENTITY ممکن است مقدار Trigger را برگرداند و IDENT_CURRENT ممکن است تحت تأثیر نشست دیگری باشد. SELECT MAX(Id) نیز در همزمانی روش بازیابی شناسه نیست.
برای INSERT چندردیفی، OUTPUT inserted.Id را در Table Variable یا نتیجه مستقیم دریافت کنید. این روش همه شناسهها را برمیگرداند و ارتباط هر ردیف ورودی با خروجی را میتوان با کلید موقت حفظ کرد.
نوع Identity ممکن است bigint باشد. تبدیل عجولانه به int پس از سالها رشد جدول به سرریز میرسد. نوع ستون، متغیر، DTO و قرارداد API باید هماهنگ و در تست ظرفیت بررسی شود.
Performance، امنیت و مشاهدهپذیری
هزینه مستقیم این توابع معمولاً ناچیز است. منشأ اصلی کندی تراکنش طولانی، Query غیر SARGable، ایندکس نامناسب، پردازش ردیفبهردیف یا Logging بیش از حد است. اندازهگیری باید کل مسیر را با Query Store، Execution Plan و Extended Events بسنجد.
نمایش @@VERSION، نام سرور، Host و Login در خروجی عمومی میتواند اطلاعات زیرساخت را افشا کند. این دادهها را در Log محافظتشده نگه دارید، دسترسی DMV را حداقلی کنید و پیش از اشتراک گزارش، مقادیر حساس را پالایش نمایید.
برای همبستهسازی رخداد، SPID را همراه زمان، نام سرور، Database، Login و یک Correlation ID برنامه ثبت کنید. SPID بهتنهایی دائمی نیست و Connection Pooling میتواند اتصال فیزیکی را میان درخواستها بازاستفاده کند.
Baseline پیش از تغییر کد ضروری است. زمان اجرا، CPU، Logical Reads، Writes، مدت قفل و اندازه Log را ثبت کنید؛ سپس فقط یک متغیر را تغییر دهید و همان بار کاری را تکرار نمایید. نتیجه قابل سنجش از ادعای کلی بهینهسازی ارزشمندتر است.
سؤالات متداول
پرسش 1: توابع سیستمی SQL Server چه هستند؟
توابع و متغیرهای سیستمی اطلاعاتی درباره آخرین دستور، نشست، Scope، جدول، تراکنش یا نمونه سرور ارائه میکنند. خروجی آنها باید با توجه به همان دامنه تفسیر شود.
پرسش 2: چرا بعضی نامها با @@ شروع میشوند؟
این شکل نامگذاری میراث Transact-SQL است و بسیاری از آنها Function سیستمی محسوب میشوند، نه متغیر عمومی قابل تغییر توسط کاربر.
پرسش 3: کدام تابع برای شناسه درج جدید بهتر است؟
برای یک ردیف در Scope جاری معمولاً SCOPE_IDENTITY مناسب است؛ برای چند ردیف، OUTPUT inserted.Id نتیجه کاملتر و ایمنتری میدهد.
پرسش 4: آیا این توابع در خدمات سازمانی کاربرد دارند؟
بله؛ کنترل عملیات، Audit، عیبیابی Blocking، ثبت Inventory و مدیریت تراکنش از کاربردها هستند. پیادهسازی باید با سیاست امنیت و مانیتورینگ سازمان هماهنگ شود.
پرسش 5: تفاوت Session و Scope چیست؟
Session همان اتصال است؛ Scope محدوده اجرای Batch، Procedure یا Trigger است. یک Session میتواند چند Scope متوالی یا تودرتو داشته باشد.
پرسش 6: آیا میتوان برای طراحی این بخش مشاوره گرفت؟
در پروژه حساس، بازبینی Triggerها، Transactionها، خطاها و Connection Pooling ارزشمند است. هدف مشاوره تبدیل مثال آموزشی به قرارداد امن و قابل آزمون است.
پرسش 7: خطای رایج مشترک چیست؟
خواندن دیرهنگام مقدار یا انتخاب تابع با دامنه اشتباه رایجترین خطاست. ثبت Context و تست همزمانی این ریسک را کاهش میدهد.
پرسش 8: این توابع چه اثر Performance دارند؟
اغلب خود تابع سبک است؛ هزینه اصلی از Query، قفل، Log یا پایش پیرامونی میآید. Query Store و Extended Events برای اندازهگیری کل جریان مناسباند.
پرسش 9: Best Practice عمومی چیست؟
مقدار را نزدیک به دستور مرجع بخوانید، نوع را صریح کنید، صفر و NULL را تست نمایید و در مسیر خطا تراکنش را با XACT_STATE مدیریت کنید.
پرسش 10: سازگاری نسخه چگونه بررسی میشود؟
Syntaxهای اصلی سابقه طولانی دارند، اما قابلیتهای مکمل و DMVها به نسخه، Edition و Compatibility Level وابستهاند. تست روی نسخه مقصد الزامی است.
سؤالات مصاحبه
سؤال 1: چرا @@IDENTITY میتواند خطرناک باشد؟
زیرا مقدار Trigger در همان Session را نیز میبیند و ممکن است شناسه جدول دیگری را برگرداند. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 2: تفاوت @@TRANCOUNT و XACT_STATE چیست؟
اولی تعداد سطحها و دومی امکان Commit و وضعیت واقعی تراکنش را نشان میدهد. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 3: چرا MAX(Id) جایگزین SCOPE_IDENTITY نیست؟
زیرا در همزمانی ممکن است ردیف نشست دیگری را انتخاب کند و به ایندکس یا اسکن اضافه نیاز دارد. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 4: چطور خطای آخر را ثبت میکنید؟
در کد جدید داخل CATCH از ERROR_NUMBER، ERROR_MESSAGE، ERROR_LINE و اطلاعات Context استفاده میکنم. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 5: آیا @@SERVERNAME همیشه نام ماشین است؟
خیر؛ نام پیکربندیشده نمونه است و پس از Rename یا در Named Instance ممکن است متفاوت باشد. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 6: SPID برای چه مدتی معتبر است؟
فقط عمر همان Session؛ پس از قطع اتصال ممکن است عدد به نشست دیگری تخصیص یابد. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 7: چگونه نسخه را قابل پردازش میخوانید؟
بهجای Parse رشته @@VERSION از SERVERPROPERTY برای ProductVersion، Edition و ProductLevel استفاده میکنم. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
سؤال 8: اولین قدم عیبیابی مقدار غیرمنتظره چیست؟
بازسازی حداقل مثال در همان اتصال و ثبت خروجی بلافاصله قبل و بعد از Statementهای مرتبط است. پاسخ کامل باید یک مثال اجرایی، حالت مرزی و اثر همزمانی یا Trigger را نیز توضیح دهد.
جمعبندی و مسیر مطالعه
توابع سیستمی این مجموعه ابزارهای کوچک اما تعیینکنندهای هستند. انتخاب درست از تشخیص مرز شروع میشود: Statement برای ROWCOUNT و ERROR، Scope یا Session برای Identity، Table برای IDENT_CURRENT، Transaction برای TRANCOUNT و Server یا Session برای اطلاعات محیط.
در پیادهسازی واقعی، مقدار را فوری ذخیره کنید، نوع را صریح سازید، خطا و تراکنش را با الگوی یکسان مدیریت نمایید و همزمانی را تست کنید. سپس با پایش مبتنی بر داده، اثر تغییر را روی Performance و قابلیت پشتیبانی بسنجید.