آپدیت داده در SQL Server: راهنما جامع UPDATE، FROM، JOIN و MERGE برای عملکرد بهینه
دستور UPDATE در SQL Server برای اصلاح رکوردهای موجود در یک جدول استفاده میشود. این دستور به شما امکان میدهد تا مقادیر یک یا چند ستون را برای یک زیرمجموعه خاص از ردیفها یا برای تمام ردیفهای یک جدول تغییر دهید. درک نحوه استفاده مؤثر از UPDATE با عباراتی مانند FROM، JOIN و MERGE برای مدیریت کارآمد دادهها حیاتی است.
روش استاندارد برای به روز رسانی یک جدول شامل تعیین دستور UPDATE و سپس نام جدول هدف است. این نام جدول را میتوان به صورت زیر در نظر گرفت:
table_name
پس از آن، عبارت SET که شامل ستونها و مقادیری است که باید به روز شوند، و یک عبارت WHERE برای فیلتر کردن ردیفها میآید. ساختار اصلی این دستور به شرح زیر است:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
این ساختار به شما امکان میدهد تا مقادیر را به صورت مستقیم در یک جدول هدف بر اساس شرایط مشخص شده به روز کنید. برای مثال، فرض کنید میخواهیم اطلاعات یک شخص را در جدول Person.Person در پایگاه داده AdventureWorks2019 به روز رسانی کنیم:
USE AdventureWorks2019;
GO
UPDATE Person.Person
SET FirstName = 'Roberto', LastName = 'Tamburello'
WHERE BusinessEntityID = 1;
این کوئری ستونهای FirstName و LastName را برای ردیفی که BusinessEntityID آن برابر با 1 است، به روز میکند. اگر عبارت WHERE حذف شود، تمام ردیفهای جدول تحت تأثیر قرار میگیرند.
در برخی موارد، نیاز به به روز رسانی یک جدول بر اساس دادههای موجود در جداول دیگر است. عبارت FROM در دستور UPDATE، که ساختار آن به صورت زیر است:
FROM table_source
روشی قدرتمند برای انجام این کار فراهم میکند. این عبارت به شما امکان میدهد تا دادهها را از چندین منبع بازیابی کرده و برای به روز رسانی جدول هدف استفاده کنید.
UPDATE T1
SET T1.column = T2.column
FROM table1 T1 JOIN table2 T2 ON T1.id = T2.id
WHERE condition;
این نمونه نحوه ارجاع به جداول T1 و T2 را در عبارت FROM نشان میدهد و سپس مقادیر را از T2 به T1 منتقل میکند. برای نشان دادن این قابلیت، میتوانیم از جدول Sales.Store و Sales.Customer در AdventureWorks2019 استفاده کنیم.
ابتدا، دو جدول موقت ایجاد میکنیم تا دادههای نمونه برای نمایش داشته باشیم:
DROP TABLE IF EXISTS #SalesStore;
CREATE TABLE #SalesStore (
BusinessEntityID INT,
Name NVARCHAR(50),
SalesPersonID INT
);
INSERT INTO #SalesStore (BusinessEntityID, Name, SalesPersonID)
SELECT BusinessEntityID, Name, SalesPersonID
FROM Sales.Store
WHERE BusinessEntityID IN (292, 294, 296, 298, 300);
DROP TABLE IF EXISTS #SalesCustomer;
CREATE TABLE #SalesCustomer (
CustomerID INT,
PersonID INT,
StoreID INT,
TerritoryID INT,
AccountNumber NVARCHAR(10)
);
INSERT INTO #SalesCustomer (CustomerID, PersonID, StoreID, TerritoryID, AccountNumber)
SELECT CustomerID, PersonID, StoreID, TerritoryID, AccountNumber
FROM Sales.Customer
WHERE StoreID IN (292, 294, 296, 298, 300);
حال، فرض کنید میخواهیم ستون StoreID در جدول #SalesCustomer را بر اساس BusinessEntityID متناظر در #SalesStore به روز کنیم. در اینجا BusinessEntityID در #SalesStore با StoreID در #SalesCustomer مطابقت دارد:
UPDATE SC
SET SC.StoreID = SS.BusinessEntityID
FROM #SalesCustomer AS SC
INNER JOIN #SalesStore AS SS
ON SC.StoreID = SS.BusinessEntityID
WHERE SC.CustomerID = 11185;
این کوئری، StoreID مشتری با CustomerID 11185 را با BusinessEntityID مربوطه از #SalesStore به روز میکند. این یک راه حل ساده و رایج برای به روز رسانی دادهها از یک جدول منبع است.
برای به روز رسانیهای شرطی که نیاز به ارزیابی پیچیدهتری دارند، میتوان از عبارت FROM با یک JOIN داخلی (INNER JOIN) استفاده کرد. این امکان به روز رسانی ردیفها را فقط در صورتی که شرط JOIN برآورده شود، فراهم میکند. این رویکرد به ویژه زمانی مفید است که شما میخواهید فقط رکوردهای خاصی را بر اساس معیارهای منطبق از یک جدول دیگر تغییر دهید.
UPDATE SC
SET SC.StoreID = 302
FROM #SalesCustomer AS SC
INNER JOIN #SalesStore AS SS
ON SC.StoreID = SS.BusinessEntityID
WHERE SC.BusinessEntityID = 292;
مثال بالا کمی متفاوت است؛ اگر BusinessEntityID از #SalesCustomer (که قبلاً ایجاد نشده است) استفاده کند، کار نمیکند. یک مثال بهتر میتواند این باشد که StoreID را در #SalesCustomer برای مشتریانی که StoreID آنها در #SalesStore وجود دارد، به روز کنیم. اگر میخواهیم StoreID را برای رکوردهای خاصی بر اساس تطابق در #SalesStore به یک مقدار ثابت (مثلاً 302) تغییر دهیم:
UPDATE SC
SET SC.StoreID = 302
FROM #SalesCustomer AS SC
INNER JOIN #SalesStore AS SS
ON SC.StoreID = SS.BusinessEntityID
WHERE SC.StoreID = 292; -- Assuming StoreID in #SalesCustomer matches BusinessEntityID in #SalesStore
در SQL Server، عبارت UPDATE همراه با عبارت JOIN یک سینتکس قدرتمند برای به روز رسانی یک جدول بر اساس دادههای جداول دیگر است. ساختار کلی JOIN به این صورت است:
JOIN | APPLY
این روش معمولاً در سناریوهایی به کار میرود که دادههای به روز رسانی شده از یک یا چند جدول مرتبط میآیند. دستور UPDATE با JOIN یک سینتکس قدرتمند برای انجام به روز رسانیهای پیچیده فراهم میکند.
UPDATE SC
SET SC.AccountNumber = 'AW' + CONVERT(NVARCHAR(10), SC.CustomerID)
FROM #SalesCustomer AS SC
INNER JOIN #SalesStore AS SS
ON SC.StoreID = SS.BusinessEntityID
WHERE SS.BusinessEntityID = 292;
این کوئری AccountNumber را برای مشتریانی که StoreID آنها با BusinessEntityID 292 در #SalesStore مطابقت دارد، به روز میکند و یک شماره حساب جدید با فرمت ‘AW’ + CustomerID ایجاد میکند.
استفاده از LEFT JOIN در UPDATE SQL Server به شما امکان میدهد تا رکوردهایی را در جدول هدف به روز کنید، حتی اگر مطابقت متناظری در جدول منبع وجود نداشته باشد. این قابلیت در سناریوهایی که میخواهید ردیفها را در جدول هدف بر اساس دادههای موجود در جدول منبع به روز کنید، اما همچنان ردیفهایی را که مطابقت ندارند حفظ و احتمالاً مقادیر خاصی را برای آنها تنظیم کنید، بسیار مفید است.
UPDATE SC
SET SC.TerritoryID = 5
FROM #SalesCustomer AS SC
LEFT JOIN #SalesStore AS SS
ON SC.StoreID = SS.BusinessEntityID
WHERE SS.BusinessEntityID IS NULL AND SC.TerritoryID = 4;
این دستور تمام مشتریان در #SalesCustomer را که StoreID آنها در #SalesStore مطابقت ندارد و TerritoryID آنها 4 است، یافته و TerritoryID آنها را به 5 به روز میکند. این یک مثال برای به روز رسانی رکوردهای ناموجود در جدول JOIN شده است.
هنگامی که نیاز به ادغام دادهها از چندین جدول برای به روز رسانی، درج (INSERT) یا حذف (DELETE) ردیفها به صورت همزمان دارید، دستور MERGE راه حلی جامع ارائه میدهد. این دستور به ویژه برای عملیات همگامسازی یا مدیریت تغییرات دادهها بین جداول منبع و هدف مفید است. MERGE به شما امکان میدهد تا یک جدول هدف را بر اساس نتیجه JOIN با یک جدول منبع دستکاری کنید. بخشهای اصلی دستور MERGE عبارتند از:
WHEN MATCHED THEN UPDATE, WHEN NOT MATCHED THEN INSERT, WHEN NOT MATCHED BY SOURCE THEN DELETE
که به شما امکان میدهد عملیات مختلف را بر اساس اینکه ردیفها در جدول منبع و هدف مطابقت دارند یا نه، تعریف کنید.
USE AdventureWorks2019;
GO
DROP TABLE IF EXISTS #TargetProducts;
CREATE TABLE #TargetProducts (
ProductID INT PRIMARY KEY,
ProductName NVARCHAR(50),
Price MONEY,
LastUpdated DATETIME DEFAULT GETDATE()
);
INSERT INTO #TargetProducts (ProductID, ProductName, Price) VALUES
(707, 'Sport-100 Helmet', 34.99),
(708, 'Road-650 Helmet', 49.99),
(709, 'Mountain-500 Helmet', 79.99);
DROP TABLE IF EXISTS #SourceProducts;
CREATE TABLE #SourceProducts (
ProductID INT PRIMARY KEY,
ProductName NVARCHAR(50),
Price MONEY
);
INSERT INTO #SourceProducts (ProductID, ProductName, Price) VALUES
(707, 'Sport-100 Helmet', 36.99), -- Update price
(710, 'Bike Wash', 8.99), -- New product (insert)
(708, 'Road-650 Helmet', 49.99); -- No change
اکنون از MERGE برای همگامسازی #TargetProducts با #SourceProducts استفاده میکنیم. این عملیات شامل به روز رسانی رکوردهای موجود، درج رکوردهای جدید و حذف رکوردهایی است که در منبع وجود ندارند:
MERGE #TargetProducts AS Target
USING #SourceProducts AS Source
ON (Target.ProductID = Source.ProductID)
WHEN MATCHED AND Target.Price <> Source.Price THEN
UPDATE SET Target.Price = Source.Price,
Target.LastUpdated = GETDATE()
WHEN NOT MATCHED BY Target THEN
INSERT (ProductID, ProductName, Price)
VALUES (Source.ProductID, Source.ProductName, Source.Price)
WHEN NOT MATCHED BY Source THEN
DELETE;
دستور MERGE فوق، جدول #TargetProducts را بر اساس #SourceProducts به روز میکند. اگر ProductID مطابقت داشته باشد و Price متفاوت باشد، ردیف Target به روز میشود. اگر ProductID در Target وجود نداشته باشد اما در Source باشد، یک ردیف جدید در Target درج میشود. اگر ProductID در Target باشد اما در Source نباشد، ردیف از Target حذف میشود.
انتخاب روش صحیح برای به روز رسانی دادهها در SQL Server به الزامات خاص و پیچیدگی عملیات شما بستگی دارد. دستور UPDATE با FROM یا JOIN برای به روز رسانیهای ساده تا متوسط که شامل دادهها از یک یا چند جدول مرتبط هستند، بسیار کارآمد است. این روشها به دلیل خوانایی و عملکرد خوب در سناریوهای معمول، به طور گستردهای مورد استفاده قرار میگیرند.
در مقابل، دستور MERGE برای سناریوهای همگامسازی پیچیدهتر که نیاز به انجام چندین نوع عملیات (UPDATE، INSERT و DELETE) در یک تراکنش واحد دارند، ایدهآل است. اگرچه MERGE قدرتمند است، اما میتواند پیچیدگی بیشتری داشته باشد و در برخی موارد ممکن است نیاز به بررسی دقیقتری از عملکرد داشته باشد.
هنگام انتخاب بین این روشها، عوامل زیر را در نظر بگیرید:
- **سادگی عملیات:** برای به روز رسانیهای مستقیم،
UPDATEباFROMیاJOINاغلب سادهتر و خواناتر است. - **نیاز به درج/حذف:** اگر علاوه بر به روز رسانی، نیاز به درج یا حذف ردیفها نیز دارید،
MERGEبهترین گزینه است. - **عملکرد:** برای حجم زیادی از دادهها، هر دو روش میتوانند عملکرد خوبی داشته باشند، اما
MERGEممکن است در برخی موارد به دلیل پیچیدگی داخلی، سربار بیشتری داشته باشد. همیشه عملکرد را با دادههای واقعی آزمایش کنید.
با درک نقاط قوت و ضعف هر یک از این روشها، میتوانید کارآمدترین و بهینهترین راه حل را برای نیازهای مدیریت داده در SQL Server خود انتخاب کنید. استفاده صحیح از UPDATE FROM، UPDATE JOIN و MERGE میتواند به طور قابل توجهی کارایی و دقت عملیات داده شما را بهبود بخشد.