SQL Server
3.93K subscribers
19 photos
7 videos
36 files
167 links
حمید رضا صادقیان

🔴طراح‌ومشاوربانک های اطلاعاتیSQLSERVER
⚫️مدرس دوره های آموزشیDatabase

ارتباط با من:
@Hamidreza_Sadeghian

گروه تبادل نظر:
https://t.me/+uIc1qhv58gU0NWQ0
Download Telegram
Forwarded from Deleted Account
Backup Internals.mp4
96.3 MB
#آموزش #SQL Server نحوه عملیات بک آپ در SQL Server و نحوه بهینه سازی عملیات بک آپ
سلام و عرض ادب خدمت دوستان گرامی
شب بر همگان خوش باشه
یکی از مواردی که در اکثر مشاوره ها در شرکتها باهاش برخورد کردم نحوه نوشتن کدها در زبان شیرین T-SQL بوده .
دوستانی که دارن کد T-SQL می نویسند باید به این نکته توجه کنند که زبان T-SQL یک زبان توصیفی یا Declarative هست.
زبانهای برنامه نویسی مثل C# یا Delphi اینها Procedural هستند.
شما نباید با همون منطقی که در زبانی مثل سی شارپ تفکر می کنید و کد می نویسید ،در زبان T-SQL هم کد بنویسید.
بارها دیدم که مشکلات خیلی راحت حل می شدن ولی چون تفکر Procedural بوده یا حلقه while در کدها تعریف شده یا از جداول Temp به شدت استفاده شده یا Cursor تعریف شده که گاها با یک Select یا update یا Insert به راحتی حل شده و Performance اون چند ده برابر نیز شده است.
زبان T-SQL از زبان SQL مشتق شده که یک زبان با استاندارد Ansi هست. این زبان از Relational Model اقتباس شده که خود Relational Model از ترکیب Set Theory و Predicate Logic ایجاد شده است.
پس وقتی که شما دارید کدنویسی می کنید باید به صورت Set Based به داده ها نگاه کنید نه یک رکورد از یک جدول.
شما نباید هیچ وقت هیچ وقت هیچ وقت در کد نویسی T-SQL برای SQL Server الگوریتم مشخص کنید. وقتی که در خیلی از موارد ترکیبی از Cursor, While ,Temp Table ها مشاهده میشه ، کاملا مشخص هست که برنامه نویس داره الگوریتم فراخوانی اطلاعات هم به SQL Server تحمیل میکنه که کاری کاملا اشتباهه.
شما در SQL Server باید به این طریق کد بنویسید که نیازتون رو بیان کنید. همین
اینکه چطوری این داده ها فراخوانی می شوند رو به Engine SQL Server بسپارید . بهتون قول میدم به بهترین نحو و با بهترین الگوریتم ها ،‌اطلاعات موردنظر شمارو فراخوانی خواهد کرد و به شما نشان خواهد داد.

اگر در این خصوص سوالی داشتید در خدمتتون هستم.

ارادتمند.
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL
سلام و عرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه
بحثی رو چند روز اخیر شروع کردم د رخصوص Set Based نوشتن و سبب سوالات بسیار زیادی در خصوصی من شد که ابهام ایجاد شده بود که چطور خود SQL Server متوجه میشه راه درست چیه.؟
تصمیم گرفتم یک ذره ساده تر مساله رو توضیح بدم و با مثالهای متعدد این بحث رو جا بندازم.
خوب بذارید از یک مثال فارسی شروع کنیم.
ما میخواهیم ده تا کتاب رو از کتابخونه از سری کتابهای علمی بگیریم که رنگ جلد آنها زرده.

این رو میشه به دو صورت بیان کرد. من در دو حالت Set Based و Cursor Based بیانش میکنم تفاوت هاش رو ببینید و خودتون زمانش رو حدس بزنید.

قسمت Set Based :
در کتابخونه به قفسه کتابهای علمی برو(From ) و از فهرست اونجا نگاه کن کتابهایی که جلد زرد رنگ دارند(Where) ده عدد(Top) جداکن بردار.


قسمت Cursor Based :
با استفاده از تاکسی ها به کتابخونه برو. حتما سوار تاکسی های زرد بشو و از تاکسی های عبوری و اتوبوس استفاده نکن.
در کتابخونه از راهروی سمت راست برو به انتهای راهرو رسیدی بپیچ به سمت چپ و از پله ها بیا پایین به انتهای راهرو برو در اونجا قفسه کتابهای علمی رو مشاهده می کنی.
حالا از پایین قفسه تک تک کتابهارو بردار رنگشون رو بررسی کن اگر رنگ اونها زرده برش دار و بذار داخل سبد اگر رنگش زرد نبود کتاب رو بذار سرجاش برو سراغ کتاب بعدی. اینکار رو تکرار کن تا ده عدد کتاب با جلد زرد رنگ رو جمع آوری کنی.

خوب اختلاف رو دیدین؟
شما به SQL Server میگید چه چیزی نیاز دارید و از کجا و چه مشخصاتی داشته باشه. اینکه چطوری اون دیتاها فراهم بشه SQL Server به واسطه Statistics ها ، به واسطه ایندکس ها و موارد دیگه بهترین الگوریتم و سریعترین الگوریتم رو برای رسیدن به دیتای شما فراهم می کنه
ولی وقتی شما میاین مطابق روش دوم براش راه حل در نظر میگیرید سبب میشه دیگه از الگوریتم های خودش پیروی نکنه و هرچی شما دیکته کردین انجام بده پس مستلزم انجام مراحل خیلی بیشتر و مسلما زمان بیشتر و درگیری منابع بیشتر هست.

وقتی من در روش اول بیان نکردم چطور برو کتابخونه ، شاید اون فرد با BRT خیلی سریعتر برسه یا با مترو. ولی در روش دوم من اجبارش کردم حتما باید با تاکسی زرد بره. که میتونه ترافیک باشه و خیلی شلوغ باشه.

در پستهای بعدی مثالهای عملی تری رو ارائه می کنم
لطفا سوالات و نظراتتون رو بامن درمیان بذارید تا بتونم کیفیت مطالبی که مینویسم رو ارتقا بدم.

ارادتمندشما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server
#قسمت_دوم
سلام وعرض ادب خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه
در پست بعد جواب سوالات مربوط به پرسشها را قرار میدم.
ممنون از همه عزیزانی که محبت کردن و وقت گذاشتن و به این پرسشها پاسخ دادن.

ممنونم از اینکه با نظرات ارزشمندتون کمک می کنید کیفیت مطالب افزایش پیدا کنه

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Quiz #Quiz_Answer
سلام و عرض ادب خدمت دوستان عزیزم
امیدوارم حال همه شما خوب و خوش باشه و براتون سلامتی و شادی آرزومندم
همونطور که میدونید در دو پست قبلی در خصوص Set Based Thinking صحبت کردم و مثال هایی رو عرض کردم.
امروز قصد دارم مقداری وارد مسائل حقیقی بشیم که باهاش سرو کار داریم.
خوب من مساله ای رو مطرح می کنم خوشحال میشم راه حل هاتون رو در خصوصی برای من ارسال کنید.
پیشاپیش از همه عزیزانی که در این سوال و جوابها شرکت می کنند تشکر میکنم چون باعث میشه انگیزه بیشتری پیدا کنم و زمان بیشتری رو صرف کنم که این مسائل جا بیافته.
متاسفانه در دانشگاهها و موسسات آموزشی اصلا به این موارد نمی پردازند. بعضی از اساتید دانشگاهها متاسفانه اصلا از دانش خوبی در این حوزه برخوردار نیستند و اگر همین مسائل رو بپرسید به سختی میتونند بهتون پاسخ بدن. همین مسائلی که من اینجا مطرح میکنم از اساتیدی که میشناسید بپرسید و پاسخهای آنها رو با جوابهایی که اینجا ارسال میشه مقایسه کنید تا خودتون به عمق فاجعه پی ببرید.
خوب برگردیم سر سوال.
یکی از مسائلی که در نرم افزارها با آن مواجه هستیم بحث پیدا کردن شماره های خالی یا Gap بین شماره اسناد یا شماره نامه ها هست
فرض کنید داده های زیر رو دارید.
Id
1
2
3
5
6
8
10
15
21
30
45
46
47
48
49
50
55
56
57
58
60
61
62
66

ما میخواهیم شماره اسنادی رو بدست بیاریم که داخل این لیست نیستند.
که جواب باید به شرح زیر باشه
4,7,9,11..14,16..20,22..29,31..44,51..54,59,63,64,65

جوابها رو تا روز یکشنبه آخروقت برای من ارسال کنید
من راه حل های مختلف رو روز دوشنبه قرار میدم و کامل دراین زمینه شرح میدم.
لطفا از اینترنت کدی برای من کپی نکنید ارسال کنید.خیلی ارزشمند نیست. میخوام خودتون بشینید به سوال فکر کنید و با دانش خودتون و مطالبی که در پرسش و پاسخ ها و پستهای قبل عرض کردم راه حل برای من بنویسید. وگرنه الان دنبال مساله Gap در اینترنت بگردید راه حلهای زیادی رو پیدا می کنید.
منتظر پاسخهای شما عزیزان هستم.
(خوشحال میشم اتفاقا از اساتید دانشگاهی که میشناسید بپرسید و راه حل های این عزیزان هم بیارید باهم بررسی کنیم☺️)

اسکریپت ساخت جدول :
Create Table #Test (Id int)
Go
Insert into #Test
Values(1),(2),(3),(5),(6),(8),(10),(15),(21),(30),(45),(46),(47),(48),(49),(50),
(55),(56),(57),(58),(60),(61),(62),(66)
Go

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Learn_SQL_Server
#قسمت_سوم
سلام و عرض ادب خدمت عزیزان و دوستان گرامی
امیدوارم که حالتون خوب باشه
قبل از هرچیزی جاداره از تمام دوستان عزیزی که محبت کردن و پاسخ هارو ارسال کردن تشکر کنم.
البته این مساله خیلی ساده بود و اصلا من قسمتهای پیچیده اوونو مطرح نکردم که سبب نوشتن کدهای سنگین بشه.
فقط صرفا هدف آشنایی با مفاهیم Set Based هست و اینکه مفهوم کدهارو متوجه بشیم.
تابع زیر برای تولید اعداد هست که تا یک بازه بزرگی رو تولید می کنه.

CREATE FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS (SELECT c FROM (SELECT 1 UNION ALL SELECT 1) AS D(c)),
L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L5)
SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
FROM Nums
ORDER BY rownum;
GO

من سه تا کد مختلف نوشتم که هر کدومش رو توضیح میدم.
کد اول :

Select n as ID from Getnums(1,66) as n
where not exists(Select * from #test as d where n.n=d.id)
در این کد من با استفاده از تابع فوق اعداد 1 تا 66 رو تولید کردم و بایک Not exists دارم چک میکنم که رکورد وجود داره یا نه. به این طریق نوشتن Select در Where Clause که سبب ارتباط با Select بالایی هست Correlated subquery می گویند.
این کد رو با not in هم می تونید بنویسید ولی performance ضعیفتری نسبت به این کد داره. در اینجا اعداد 1 تا 66 ایجاد شده و براساس شرط داخلی سلکت در Where چک می شود که آیا رکورد فوق True هست یا False . به همین خاطر از سرعت پردازش بالایی برخورداره .
روش دوم :
Select n as ID from Getnums(1,66) as n
except
Select Id from #test

در این روش یک مرحله اضافه وجود داره و این هم بحث Sort و Distinct هست که خود عملیات Except سبب اون خواهد شد و باعث میشه نسبت به کد بالایی از Performance پایین تری برخوردار باشه.

روش سوم :
Select n as ID from Getnums(1,66) as n
Left outer Join #test as d
on n.n=d.id
where d.id is null

این روش هم نسبت به روش اول تقریبا کندتر هست .
الان خیلی نمیخوام وارد جزئیات مسائل Performance بشم.
باز هم تاکید میکنم مساله رو هم ساده انتخاب کردم هم روشهای ساده ای نوشتم که با طرز تفکر Set Based در مسائل مختلف آشنا بشین. جلوتر که بریم مسائل پیچیده تر و منطق های پیچیده تری رو حتما بررسی می کنیم و هم اینکه نکات Performance رو عرض می کنم.

با روشهای Cursor Based هم بخواهید بنویسید میشه با یک حلقه چک کرد ببینیم آیا رکورد فوق موجود هست یاخیر که نسبت به این روشها کندتر خواهد شد.

ارادتمند شما
حمیدرضا صادقیان
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server

#Set_Based_Thinking #T_SQL #SQL_Server #SQLServer #Hamidreza_Sadeghian #Declarative #SQL_Server #Learn_SQL_Server
#قسمت_چهارم
👍2
سلام وعرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوب باشه
شاید بارها پیش اومده باشه براتون که نیاز داشته باشین روی نتیجه SP ها سلکت بزنین و شرط بذارین یا از نتیجه اون در Join ها استفاده کنید.
خوب راه معمولش این هست که نتیجه SP رو داخل یک جدول موقت بریزین و بعد از اون جدول استفاده کنید.
یک راه ساده تر این هست که از Openrowset استفاده کنید.
برای استفاده از OpenrowSet ابتدا باید دستور زیر رو اجرا کنید.
sp_configure 'Ad Hoc Distributed Queries',1
Go
Reconfigure
go

سپس میتونید از این قالب استفاده کنید.
select a.* from openrowset('sqlncli','server=.;trusted_connection=yes;','
exec DbName.dbo.UspReturnPersonelList
''01-11-2018'',''29-12-2018''') as a
where a.[name] =N'Hamidreza'

در این کد در قسمت Trusted_Connection من از Windows_Authentication استفاده کردم و در قسمت Server هم نام سرور لوکال خودم رو قرار دادم. که میتونه نام هر سروری و باهر دسترسی باشه.
و درنهایت نام دیتابیس به همراه Schema رو با نام SP صدا زدم و بهش دوتا پارامتر تاریخ پاس دادم.

نکته : اگر حجم داده ها زیاد هست و نیاز دارید خیلی از این داده ها استفاده کنید پیشنهاد میکنم از جدول استفاده کنید. چون روی جدول شما قابلیت ایندکس گذاری نیز دارید . این مورد برای زمانهایی هست که یا حجم داده ها کمتر هستن یا تعداد استفاده آنها خیلی کم هست.

امیدوارم از این نکته لذت ببرید ☺️☺️

ارادتمند شما
حمیدرضا صادقیان



#openRowset #SQL_Server #TSQL #SP #Stored_Procedure
ID:@Hamidreza_Sadeghian
Channel :@SQL_Server
SQL Server Group :https://t.me/joinchat/BTQQtzy50j_MVbMcUf6PtA
دوره بسیار عالی با افرادی بسیار دقیق و باهوش در شرکت موتورسازان تراکتور سازی تبریز

#performance_tuning
#T_SQL
#SQL_Server
👍1
سلام و عرض ادب خدمت دوستان عزیزم

یکی از مسائلی که اکثر قریب به اتفاق شرکت ها با اون دست و پنجه نرم می کنند عدم وجود سورس کنترل و ورژن کنترل بر روی دیتابیس هست وبرای هندل کردن این مورد میان از ابزارهایی مثل RedGate استفاده می کنند که متاسفانه نمیتونه چرخه DLM رو تکمیل کنه.

استفاده از Database Project یا همون SSDT به شما کمک میکنه چرخه DLM رو پیاده سازی کنید.
می تونید برای دیتابیس ها Unit Test بنویسید ، چیزی که من تقریبا در هیچ شرکت و یا سازمانی اصلا ندیدم و حتی متاسفانه دانشش وجود نداشت.
همچنین میتونید برای دیتابیس ها محیط Test,UAT,PRoduction ایجاد کنید و پابلیش های مختلفی داشته باشین.
همزمان چندین نفر می تونن بر روی دیتابیس تغییرات اعمال کنند بدون اینکه باهم تداخلی داشته باشه.
دسترسی ها از روی محیط عملیاتی کاملا حذف میشه .
هیچ وقت تداخل تغییرات به وجود نمیاد
به راحتی میتونید ورژن های مشتریان و دیتابیس های عملیاتی ر وکنترل کنید و تغییرات رو داشته باشید و بر روی مقصد اعمال کنید.
اگر تصمیم دارید یک چرخه دقیق مهندسی نرم افزار رو پیاده سازی کنید پیشنهاد می کنم حتما چرخه DLM رو در سازمان یا شرکتتون پیاده سازی کنید.
میتونید Build های اتوماتیک پیاده سازی کنید.
خیلی راحت میتونید Refactoring بر روی دیتابیس انجام بدین بدون اینکه نگران باشید ممکنه در یک شی در داخل دیتابیس یک چیزی تغییر کرده باشه که در جاهای دیگه تغییر نکرده و میتونه در یک جایی باعث از کار افتادن سیستم بشه.

پیشنهاد می کنم برای درک صحیح از صحبتهایی که عرض کردم فیلم زیر رو حتما ببینید

ارادتمند شما
حمیدرضا صادقیان
ID: @Hamidreza_Sadeghian

#DLM #DAtabase_Project #Database_Lifecycle_Management #SQL_Server #CI

https://channel9.msdn.com/Events/TechEd/Europe/2014/DBI-B312
👍1
سلام و عرض ادب خدمت دوستان عزیز
امیدوارم حالتون خوب باشه

بعضی وقتها از من سوال میکنند چیکار کنیم که نسبت به رفتارهای درونی SQL Server بیشتر آشنا بشیم و بفهمیم چیکار میکنه.
میخوام بهتون تکنیکی رو یاد بدم که بهتون دید خوبی میده.
همونطور که میدونید ابزار SSMS برای کار با SQL Server هست و خوب تقریبا اکثر کارها به واسطه اون انجام میشه. پشت اون یک سری کد نوشته شده که نشاندهنده بخشی از ساختار SQL Server هست.
برای اینکه با دستورات و جداول سیستمی خوب اشنا بشین و ارتباطاتش رو درست درک کنید ، پیشنهاد می کنم Profiler رو اجرا کنید و شروع کنید به کارکردن با قسمتهای مختلف SSMS .!
اون موقع به راحتی میتونید کدهایی که توسط SSMS داره اجرا میشه رو ببینید و با دستورات و جداول سیستمی ، توابع و پراسیجرها ، DMV ها و... آشنا بشین ، ارتباطاتش رو بدست بیارین و کلی دانش خوب نسبت به رفتار SQL Server کسب کنید.

امیدوارم این نکته در جهت افزایش دانایی به کارتون بیاد.

شادو پرانرژی باشید.

حمیدرضا صادقیان

@Hamidreza_Sadeghian

#SSMS
#Profiler
#DMV
#SQLServerEngine
#SQLServer
#SQL_Server
👍2
سلام خدمت دوستان عزیزم
امیدوارم حالتون خوب باشه
یکی از چالش هایی که ممکنه وجود داشته باشه بدست آوردن دیتاتایپ و مابقی مشخصات یک فیلد هست که نیاز هست یا از sysobjects بیاید Select کنید یا اینکه از information_schema.Columns استفاده کنید.
ولی یک راه حل ساده تر استفاده از تابع SQL_Variant_Property هست . درواقع این تابع مشخصات مقادیر از نوع SQL_Variant رو بهتون میده . با این تابع ، نوع فیلد ، طول فیلد ، Collation ، Total Byte, Maxlength رو میتوونید مشخص کنید.
به این مثال توجه کنید.
Use AdventureWorks2019
go
select SQL_VARIANT_PROPERTY(Name,'BaseType'),
SQL_VARIANT_PROPERTY(Name,'TotalBytes'),
SQL_VARIANT_PROPERTY(Name,'MaxLength')
from Production.Product

Go
با این کد هم نوع فیلد Name مشخص میشه هم تعداد بایتی که در هر رکورد ذخیره شده برای اون فیلد و هم ماکزیمم اون فیلدرو نشون میده.

امیدوارم لذت برده باشین.
شاد و پرانرژی باشید☺️☺️

حمیدرضا صادقیان
@Hamidreza_Sadeghian
#SQL_Variant_Property
#TSQL_Tips
سلام خدمت دوستان عزیزم
امیدوارم حالتون عالی عالی باشه
من در سایت Youtube یک کانال ایجاد کردم و فیلمهای آموزشی رو در اونجا قرار میدم.
میتونید با عضویت در اون کانال، به فیلمهای جدید دسترسی سریعتر پیدا کنید.

لینک فیلمها رو هم در کانال قرار خواهم داد.
اولین فیلم هم در خصوص تراکنش ها در SQL Server هست که لینکش رو براتون قرار خواهم داد.

https://www.youtube.com/watch?v=X1dFo6VNVTA

شاد و پرانرژی باشید
حمیدرضا صادقیان
@Hamidreza_Sadeghian
سلام خدمت دوستان عزیزم
امیدوارم حالتون عالی عالی باشه
آموزش نصب SQL Server 2017 رو در Youtube قرار دادم
امیدوارم که مفید واقع بشه

شاد و پرانرژی باشید
@Hamidreza_Sadeghian

https://www.youtube.com/watch?v=IB-1FabtnKo

#sql #SQLServerinstallation #SQLServer2017 #InstallSQL #SQLInstall
سلام خدمت دوستان عزیزم
امیدوارم عالی عالی باشین

دیروز یکی از دوستانم یک سوالی ازم پرسید در خصوص استفاده از تابع Round.

چالشش این بود که دوتا مقدار داره که اعشاری هستند . میخواد اگه حاصلضرب این دوتا اعشاری شد بدون اینکه رندی اتفاق بیافته قسمت حقیقی اونو نشون بده.

مثلا فرض کنید

1.5*1.8 = 2.7 . اگه رند بشه خوب میشه ۳ یا اگه کمتر از ۲.۵ باشه میشه ۲ . ولی این میخواد در هر حالتی عدد ۲ برگرده.

خوب میتونه از تابع Round استفاده کنه.

Round(1.5*1.8,0,1)

که اون پارامتر اخر دقیقا همین کارو میکنه و قسمت اعشاری رو Truncate میکنه.

چالش اینجا بود سر این دو عدد با این که ضربش یک عدد حقیقی میشد ولی یک ریال کسر میکرد ازش.

۱۳۵.۷ * ۳۵۹۴۰۰ = ۴۸۷۷۰۵۸۰ باید بشه ولی عدد ۴۸۷۷۰۵۷۹ رو این تابع برمیگردوند.

برام خیلی جالب بود . رفتم دیتا تایپهای دیتابیسش رو بررسی کردم دیدم جفت فیلدهارو از نوع Float گرفته. اونارو به Decimal تبدیل کردیم درست شد.

احتمالا شاید اگه شما هم چنین خطاهای محاسباتی دارید بیاید از دیتاتایپ های دقیقتر استفاده کنید که چنین مشکلاتی نداشته باشین.

شاد باشین و شکرگزار
حمیدرضا صادقیان
@Hamidreza_Sadeghian

#TSQL

#SQL
👍2914👌7👏1