آموزش جامع تابع OBJECT_NAME در SQL Server با ۱۰ مثال عملی
در بسیاری از اسکریپتهای مدیریتی، عدد یا نام خام بهتنهایی برای تصمیمگیری کافی نیست و باید به Metadata قابل فهم تبدیل شود. در این مقاله، OBJECT_NAME از سطح مقدماتی تا سناریوهای حرفهای بررسی میشود و هر مثال با خروجی نمونه ارائه شده است.
در ابزارهای پایش، گزارشهای مدیریتی و تحلیل DMVها معمولاً شناسه شیء دریافت میشود و این تابع آن شناسه را به نام خوانا تبدیل میکند. تمرکز آموزش بر این است که OBJECT_NAME در چه Contextی اجرا شود، نتیجه آن چگونه تفسیر شود و چه زمانی باید از یک DMV یا کاتالوگویوی جایگزین کمک گرفت.
برای مشاهده جایگاه OBJECT_NAME میان سایر توابع و شمارندهها، راهنمای جامع توابع کمکی کارایی و Metadata در SQL Server را نیز مطالعه کنید.
تعریف و کاربرد اصلی OBJECT_NAME
تابع OBJECT_NAME شناسه عددی یک شیء دارای محدوده اسکیما را به نام همان شیء در پایگاه داده تبدیل میکند. این تعریف در ظاهر کوتاه است، اما استفاده درست از OBJECT_NAME به درک مفاهیمی مانند object_id، database_id و sys.objects وابسته است.
قاعده عملی OBJECT_NAME: ابتدا ورودی و Context را معتبر کنید، سپس خروجی را با نوع داده و معنای واقعی آن تفسیر کنید.
Syntax تابع یا متغیر OBJECT_NAME
SELECT OBJECT_NAME ( object_id [ , database_id ] ) AS Result;
پارامترهای OBJECT_NAME
| پارامتر | توضیح |
|---|
| object_id | شناسه شیء مانند جدول، View، Procedure یا Function. |
| database_id | شناسه اختیاری پایگاه دادهای که شیء در آن قرار دارد. |
نوع خروجی و رفتار NULL در OBJECT_NAME
sysname؛ در صورت نامعتبر بودن شناسه، نبود مجوز مشاهده Metadata یا اشاره نادرست به پایگاه داده مقدار NULL برمیگردد. در کد تولیدی بهتر است نوع مقصد بهصورت صریح تعیین شود؛ زیرا تبدیل ضمنی میتواند مقایسه، مرتبسازی یا ذخیره نتیجه OBJECT_NAME را مبهم کند.
مفاهیم کلیدی مرتبط با OBJECT_NAME
- object_id
- database_id در مبحث OBJECT_NAME
- sys.objects در مبحث OBJECT_NAME
- schema در مبحث OBJECT_NAME
- metadata در مبحث OBJECT_NAME
- NULL در مبحث OBJECT_NAME
- VIEW DEFINITION
تصویر نخست، ارتباط OBJECT_NAME را با مفاهیم اختصاصی object_id، database_id، sys.objects و schema نشان میدهد؛ این روابط مبنای انتخاب ورودی و تفسیر خروجی هستند.
سناریوهای واقعی استفاده از OBJECT_NAME
سناریوی 1 برای OBJECT_NAME، «خواناسازی گزارش قفلها» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 2 برای OBJECT_NAME، «تبدیل object_id در DMVهای ایندکس» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 3 برای OBJECT_NAME، «ثبت نام جدول در لاگ عیبیابی» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 4 برای OBJECT_NAME، «گزارش اشیای پرتغییر» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
مثالهای عملی OBJECT_NAME از ساده تا حرفهای
مثال 1: تبدیل شناسه جدول به نام
شناسه جدول sys.objects را به نام قابل خواندن تبدیل میکنیم. این سناریو بهطور اختصاصی برای درک رفتار OBJECT_NAME طراحی شده است.
SELECT OBJECT_NAME(OBJECT_ID(N'dbo.SampleOrders')) AS ObjectName;
در سامانه واقعی، نام جدول موجود خود را جایگزین کنید. هنگام استفاده سازمانی از OBJECT_NAME، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 2: نمایش نام اشیای کاربر
فهرست اشیای کاربر را همراه نامی که تابع تولید میکند میبینیم. این سناریو بهطور اختصاصی برای درک رفتار OBJECT_NAME طراحی شده است.
SELECT TOP (5)
o.object_id,
OBJECT_NAME(o.object_id) AS ObjectName,
o.type_desc
FROM sys.objects AS o
WHERE o.is_ms_shipped = 0
ORDER BY o.object_id;
| object_id | ObjectName | type_desc |
|---|
| 245575913 | Customers | USER_TABLE |
این روش برای خواناسازی خروجی کاتالوگویوها مناسب است. هنگام استفاده سازمانی از OBJECT_NAME، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 3: ترکیب نام Schema و شیء
برای ساخت نام دو بخشی، OBJECT_NAME را با OBJECT_SCHEMA_NAME ترکیب میکنیم. این سناریو بهطور اختصاصی برای درک رفتار OBJECT_NAME طراحی شده است.
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(OBJECT_ID(N'dbo.Customers'))) +
N'.' +
QUOTENAME(OBJECT_NAME(OBJECT_ID(N'dbo.Customers'))) AS TwoPartName;
| TwoPartName |
|---|
| [dbo].[Customers] |
خروجی دو بخشی برای گزارش و SQL پویا امنتر و دقیقتر است. هنگام استفاده سازمانی از OBJECT_NAME، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 4: استفاده در گزارش ایندکس
نام جدول را در کنار شناسههای گزارش ایندکس نمایش میدهیم. این سناریو بهطور اختصاصی برای درک رفتار OBJECT_NAME طراحی شده است.
SELECT TOP (10)
i.object_id,
OBJECT_NAME(i.object_id) AS TableName,
i.index_id,
i.name AS IndexName
FROM sys.indexes AS i
WHERE i.object_id > 0
AND OBJECTPROPERTY(i.object_id, N'IsUserTable') = 1
ORDER BY i.object_id, i.index_id;
| object_id | TableName | index_id | IndexName |
|---|
| 245575913 | Customers | 1 | PK_Customers |
تابع فقط نام شیء را میدهد؛ Schema را جداگانه اضافه کنید. هنگام استفاده سازمانی از OBJECT_NAME، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
تصویر دوم، جریان اجرای OBJECT_NAME را از ورودی و اعتبارسنجی تا تولید خروجی نمایش میدهد و نشان میدهد که metadata در کدام مرحله باید کنترل شود.
ادامه مثالهای پیشرفته OBJECT_NAME
مثال 5: مدیریت شناسه نامعتبر
رفتار تابع در برابر object_id نامعتبر را کنترل میکنیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
DECLARE @ObjectId int = -999;
SELECT COALESCE(OBJECT_NAME(@ObjectId), N'شیء پیدا نشد') AS SafeObjectName;
| SafeObjectName |
|---|
| شیء پیدا نشد |
NULL را صریح مدیریت کنید تا گزارش مبهم نباشد. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
مثال 6: تبدیل شناسه در پایگاه مشخص
پارامتر database_id را برای شیء موجود در پایگاه جاری بهکار میبریم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
SELECT OBJECT_NAME(
OBJECT_ID(N'sys.objects'),
DB_ID()
) AS ObjectNameInCurrentDatabase;
| ObjectNameInCurrentDatabase |
|---|
| objects |
برای پایگاه دیگر، مجوز Metadata و شناسه درست ضروری است. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
مثال 7: ثبت نام شیء در لاگ موقت
یک پیام عیبیابی با نام شیء و شناسه آن میسازیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
DECLARE @ObjectId int = OBJECT_ID(N'dbo.Customers');
SELECT CONCAT(
N'ObjectId=', @ObjectId,
N'; Name=', COALESCE(OBJECT_NAME(@ObjectId), N'NULL')
) AS DiagnosticMessage;
| DiagnosticMessage |
|---|
| ObjectId=245575913; Name=Customers |
پیام شامل شناسه و نام، عیبیابی رخدادها را سادهتر میکند. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
مثال 8: فیلتر بر اساس نام تبدیلشده
در یک گزارش کوچک، فقط شیئی را که نام موردنظر دارد نگه میداریم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
SELECT o.object_id, OBJECT_NAME(o.object_id) AS ObjectName
FROM sys.objects AS o
WHERE o.is_ms_shipped = 0
AND OBJECT_NAME(o.object_id) = N'Customers';
| object_id | ObjectName |
|---|
| 245575913 | Customers |
برای فیلترهای پرتکرار بهتر است مستقیماً از ستون name استفاده شود تا تابع روی همه ردیفها اجرا نشود. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
مثال 9: روش اشتباه و نسخه اصلاحشده
نام بدون Schema ممکن است مبهم باشد؛ نسخه اصلاحی نام کامل را میسازد. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
SELECT
OBJECT_NAME(OBJECT_ID(N'dbo.Customers')) AS IncompleteName,
CONCAT(
QUOTENAME(OBJECT_SCHEMA_NAME(OBJECT_ID(N'dbo.Customers'))),
N'.',
QUOTENAME(OBJECT_NAME(OBJECT_ID(N'dbo.Customers')))
) AS CompleteName;
| IncompleteName | CompleteName |
|---|
| Customers | [dbo].[Customers] |
برای مستندات عملیاتی، نام Schema را حذف نکنید. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
مثال 10: بهینهسازی گزارش Metadata
ابتدا ردیفها را محدود میکنیم و سپس نام را تبدیل میکنیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون OBJECT_NAME است.
WITH TargetObjects AS
(
SELECT TOP (20) object_id, type_desc
FROM sys.objects
WHERE type = N'U'
ORDER BY modify_date DESC
)
SELECT object_id,
OBJECT_NAME(object_id) AS ObjectName,
type_desc
FROM TargetObjects;
| object_id | ObjectName | type_desc |
|---|
| 245575913 | Customers | USER_TABLE |
محدود کردن مجموعه ورودی پیش از فراخوانی تابع، هزینه گزارش را کاهش میدهد. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از OBJECT_NAME جلوگیری میکند.
خطاهای رایج در کار با OBJECT_NAME
خطای 1 در استفاده از OBJECT_NAME
نام خروجی شامل نام Schema نیست؛ برای نام دو بخشی باید SCHEMA_NAME و OBJECT_SCHEMA_NAME را نیز بهکار برد. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه OBJECT_NAME را پیش از ادامه منطق با شرط صریح کنترل کنید.
خطای 2 در استفاده از OBJECT_NAME
در جستوجوی بینپایگاهدادهای باید database_id درست باشد و مجوز مشاهده Metadata وجود داشته باشد. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه OBJECT_NAME را پیش از ادامه منطق با شرط صریح کنترل کنید.
خطای 3 در استفاده از OBJECT_NAME
برای شناسههای اشیای داخلی یا موقت ممکن است نتیجه با انتظار توسعهدهنده متفاوت باشد. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه OBJECT_NAME را پیش از ادامه منطق با شرط صریح کنترل کنید.
ملاحظات Performance برای OBJECT_NAME
از نظر کارایی، OBJECT_NAME زمانی کمهزینه باقی میماند که روی یک مقدار هدفمند یا مجموعه محدود اجرا شود. فراخوانی آن روی هزاران ردیف بدون Predicate اولیه میتواند CPU و زمان گزارش را افزایش دهد.
اگر گزارش به چند Property از چندین شیء نیاز دارد، استفاده Set-based از کاتالوگویو یا DMV مرتبط با object_id معمولاً بهتر از تکرار OBJECT_NAME برای هر سلول است.
در Jobهای دورهای، نتیجه OBJECT_NAME را همراه Timestamp ذخیره کنید، اما Frequency نمونهبرداری را متناسب با سرعت تغییر داده انتخاب کنید. جمعآوری بیش از حد، جدول تاریخچه را بدون ارزش تحلیلی بزرگ میکند.
برای محاسبات عددی پیرامون OBJECT_NAME، نوع داده را قبل از ضرب یا تفریق ارتقا دهید و در سناریوهای تجمعی، Restart و بازنشانی Baseline را در نظر بگیرید.
Best Practiceهای اختصاصی OBJECT_NAME
- ورودی OBJECT_NAME را از نام یا شناسه معتبر و دارای Schema یا Context روشن تأمین کنید.
- نتیجه NULL در OBJECT_NAME را از مقدار صفر، false یا رشته خالی جدا نگه دارید.
- نوع خروجی OBJECT_NAME را پیش از ذخیره یا مقایسه به نوع مقصد مناسب تبدیل کنید.
- در گزارشهای بزرگ، گزینه Set-based مرتبط با object_id را ارزیابی کنید.
- زمان Capture، نام Database و در صورت نیاز @@SPID را کنار نتیجه OBJECT_NAME ثبت کنید.
- مجوز مشاهده Metadata یا DMV را با حداقل سطح دسترسی لازم تنظیم کنید. در مبحث OBJECT_NAME
- مثالهای OBJECT_NAME را روی نسخه و Edition واقعی محیط هدف آزمایش کنید.
- برای SQL پویا، خروجی نامی OBJECT_NAME را با QUOTENAME و پارامترسازی ایمن مصرف کنید.
تصویر سوم، تفاوت روش پرخطر و Best Practice در استفاده از OBJECT_NAME را مقایسه میکند؛ هدف آن جلوگیری از خطاهای مربوط به نام خروجی شامل نام Schema نیست؛ برای نام دو بخشی باید SCHEMA_NAME و OBJECT_SCHEMA_NAME را نیز بهکار برد. و بهبود تصمیمگیری فنی است.
سؤالات متداول اختصاصی OBJECT_NAME
OBJECT_NAME دقیقاً چه مسئلهای را در SQL Server حل میکند؟
تابع OBJECT_NAME شناسه عددی یک شیء دارای محدوده اسکیما را به نام همان شیء در پایگاه داده تبدیل میکند. در عمل، در ابزارهای پایش، گزارشهای مدیریتی و تحلیل DMVها معمولاً شناسه شیء دریافت میشود و این تابع آن شناسه را به نام خوانا تبدیل میکند. بنابراین استفاده از OBJECT_NAME زمانی ارزشمند است که خروجی آن در یک تصمیم فنی روشن مصرف شود، نه اینکه فقط برای نمایش عدد یا نام به کار رود.
نوع خروجی OBJECT_NAME چیست و چگونه باید آن را مدیریت کرد؟
نوع خروجی این ابزار چنین است: sysname؛ در صورت نامعتبر بودن شناسه، نبود مجوز مشاهده Metadata یا اشاره نادرست به پایگاه داده مقدار NULL برمیگردد. بهتر است پیش از تبدیل نوع، مقایسه یا درج در جدول گزارش، حالت NULL و محدوده مقدار را صریح کنترل کنید تا رفتار OBJECT_NAME قابل پیشبینی بماند.
آیا OBJECT_NAME در گزارشهای سازمانی کاربرد تجاری دارد؟
بله. در سناریوهایی مانند خواناسازی گزارش قفلها و تبدیل object_id در DMVهای ایندکس، خروجی OBJECT_NAME میتواند کیفیت گزارش مدیریتی را بالا ببرد. ارزش تجاری زمانی ایجاد میشود که این داده به هشدار، ظرفیتسنجی یا کاهش زمان عیبیابی متصل شود.
استفاده از OBJECT_NAME در پروژههای بزرگ چه مزیتی دارد؟
در پروژه بزرگ، استانداردسازی نحوه استفاده از OBJECT_NAME باعث میشود تیم توسعه، DBA و پشتیبانی یک تعریف مشترک از object_id و database_id داشته باشند. این هماهنگی خطاهای تفسیر و دوبارهکاری را کاهش میدهد.
تفاوت OBJECT_NAME با گزینه نزدیک آن چیست؟
OBJECT_NAME از شناسه به نام میرود، در حالی که OBJECT_ID مسیر معکوس یعنی نام به شناسه را انجام میدهد. انتخاب صحیح باید بر اساس حجم داده، نیاز به خروجی Set-based و سطح جزئیات گزارش انجام شود؛ یک تابع scalar همیشه جایگزین کاتالوگویو یا DMV کامل نیست.
برای طراحی اسکریپت حرفهای مبتنی بر OBJECT_NAME چه خدماتی لازم میشود؟
در پروژههای حساس میتوان منطق OBJECT_NAME را در قالب رویه مانیتورینگ، Dashboard، گزارش زمانبندیشده یا کنترل Deployment پیاده کرد. تحلیل نیاز، تست روی نسخه واقعی SQL Server و مستندسازی خروجی، بخشهای مهم خدمات مشاوره و انجام پروژه هستند.
رایجترین خطا هنگام کار با OBJECT_NAME چیست؟
یکی از خطاهای مهم این است که نام خروجی شامل نام Schema نیست؛ برای نام دو بخشی باید SCHEMA_NAME و OBJECT_SCHEMA_NAME را نیز بهکار برد. همچنین نادیده گرفتن NULL یا Context اجرای Query میتواند نتیجهای ظاهراً معتبر ولی از نظر عملیاتی اشتباه تولید کند.
آیا فراخوانی زیاد OBJECT_NAME بر Performance اثر میگذارد؟
یک فراخوانی منفرد معمولاً سبک است، اما اجرای OBJECT_NAME روی مجموعه بسیار بزرگ یا در شرطی که برای هر ردیف محاسبه شود میتواند هزینه ایجاد کند. ابتدا ردیفها را محدود کنید و در گزارشهای وسیع، جایگزین Set-based را ارزیابی کنید.
بهترین روش استفاده از OBJECT_NAME چیست؟
بهترین روش این است که ورودی OBJECT_NAME اعتبارسنجی، نوع خروجی صریح، حالت NULL مدیریت و نتیجه همراه زمان و Context ثبت شود. همچنین باید مشخص باشد که خروجی برای نمایش، کنترل ایمنی یا تصمیم کارایی مصرف میشود.
OBJECT_NAME با کدام نسخههای SQL Server سازگار است؟
در نسخههای رایج SQL Server پشتیبانی میشود و رفتار اصلی آن پایدار است. با این حال، هنگام انتقال اسکریپت به Azure SQL یا Edition دیگر، Propertyها، مجوزهای Metadata و تفاوتهای پلتفرم را روی همان محیط آزمایش کنید.
سؤالات مصاحبه درباره OBJECT_NAME
در مصاحبه چگونه تفاوت ورودی و خروجی OBJECT_NAME را توضیح میدهید؟
پاسخ مناسب باید Syntax یعنی OBJECT_NAME ( object_id [ , database_id ] )، نوع خروجی و شرایط NULL را توضیح دهد و یک نمونه از خواناسازی گزارش قفلها ارائه کند.
چه زمانی بهجای OBJECT_NAME از کاتالوگویو یا DMV استفاده میکنید؟
وقتی گزارش چندین ردیف و چند Property نیاز دارد، روش Set-based معمولاً مناسبتر است؛ OBJECT_NAME برای تبدیل یا بررسی هدفمند یک مقدار بسیار خواناست.
چگونه نتیجه نامعتبر OBJECT_NAME را از مقدار false یا صفر جدا میکنید؟
با بررسی صریح IS NULL، اعتبارسنجی ورودی و در صورت نیاز Join با Metadata منبع، علت نتیجه را روشن میکنم. این توضیح بهطور اختصاصی به OBJECT_NAME مربوط است.
چه نکته Performance درباره OBJECT_NAME مهم است؟
فراخوانی را پس از محدود کردن مجموعه داده انجام میدهم و از محاسبه تکراری OBJECT_NAME در SELECT و WHERE جلوگیری میکنم.
یک سناریوی واقعی برای OBJECT_NAME بیان کنید.
سناریوی مناسب میتواند ثبت نام جدول در لاگ عیبیابی باشد؛ در آن خروجی همراه Timestamp، نام Database و شناسه نشست ثبت میشود تا قابل پیگیری باشد.
چکلیست نهایی استفاده از OBJECT_NAME
- Syntax OBJECT_NAME و ورودیهای آن با نسخه هدف تطبیق داده شده است.
- Context پایگاه داده یا Instance برای OBJECT_NAME روشن است.
- مجوز لازم برای Metadata یا DMV بررسی شده است. در مبحث OBJECT_NAME
- NULL، مقدار نامعتبر و حالت مرزی OBJECT_NAME تست شده است.
- نمونه خروجی با نوع داده واقعی مقایسه شده است. در مبحث OBJECT_NAME
- در Query بزرگ، هزینه فراخوانی تکراری OBJECT_NAME اندازهگیری شده است.
- جایگزین Set-based برای گزارش انبوه ارزیابی شده است. در مبحث OBJECT_NAME
- نتیجه نهایی همراه Timestamp و توضیح عملیاتی ثبت میشود. در مبحث OBJECT_NAME
جمعبندی آموزش OBJECT_NAME
OBJECT_NAME ابزاری کوچک اما مؤثر برای در ابزارهای پایش، گزارشهای مدیریتی و تحلیل DMVها معمولاً شناسه شیء دریافت میشود و آن شناسه را به نام خوانا تبدیل میکند. است. استفاده حرفهای از آن به اعتبارسنجی ورودی، تفسیر نوع خروجی، کنترل NULL و انتخاب Scope مناسب وابسته است.
پس از تسلط بر OBJECT_NAME، برای مقایسه آن با سایر ابزارهای این مجموعه به مقاله مادر توابع کمکی Performance و Metadata در SQL Server بازگردید.
خدمات برنامهنویسی و پایگاه داده
برنامهنویسی در اصفهان
قبول سفارشهای برنامهنویسی و پایگاه داده: 09131253620
انجام پروژههای برنامهنویسی، آموزش برنامهنویسی و آموزش پایگاه داده SQL Server با رویکرد حرفهای، مستند و قابل توسعه انجام میشود.
مجموعهای معتبر با سابقه فعالیت حرفهای از سال ۱۳۷۵ شمسی
از سال ۱۳۷۵ شمسی تاکنون در زمینه طراحی و اجرای پروژههای برنامهنویسی، پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری فعالیت میکنیم.
برای سفارش پروژههای برنامهنویسی و پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری جدید، با شماره تلفن همراه 09131253620 تماس حاصل فرمایید.
ایتا، واتساپ و تماس مستقیم: +989131253620
تماس با ما