درج داده در SQL با INSERT INTO SELECT: راهنمای جامع و مثالهای کاربردی
دستور SQL INSERT INTO SELECT برای کپی کردن دادهها از یک جدول به جدول دیگر استفاده میشود. این دستور به شما امکان میدهد تا رکوردها را از یک کوئری انتخاب (SELECT statement) دریافت کرده و در یک جدول موجود (جدول مقصد) درج کنید.
سینتکس عمومی دستور INSERT INTO SELECT به صورت زیر است:
INSERT INTO TargetTable (Column1, Column2, Column3, ...)
SELECT Column1, Column2, Column3, ...
FROM SourceTable
WHERE Condition;
در این ساختار:
- TargetTable: نام جدولی است که میخواهید دادهها را در آن درج کنید. این جدول باید از قبل وجود داشته باشد.
- Column1, Column2, …: ستونهایی از TargetTable هستند که میخواهید دادهها را در آنها درج کنید.
- SELECT Column1, Column2, …: کوئری SELECT که دادهها را از SourceTable انتخاب میکند.
- SourceTable: نام جدولی است که دادهها از آن کپی میشوند.
- WHERE Condition: (اختیاری) شرطی است که ردیفهای خاصی را برای کپی کردن مشخص میکند. اگر این بخش حذف شود، تمام ردیفها از SourceTable کپی میشوند.
ایجاد جداول و درج داده اولیه
برای نشان دادن نحوه عملکرد INSERT INTO SELECT، اجازه دهید ابتدا یک جدول منبع (SourceTable) و یک جدول مقصد (TargetTable) ایجاد کنیم.
ابتدا جدول SourceTable را ایجاد و با دادهها پر میکنیم:
CREATE TABLE SourceTable (
ID INT PRIMARY KEY,
Name VARCHAR(50),
City VARCHAR(50)
);
INSERT INTO SourceTable (ID, Name, City) VALUES (1, 'Ali', 'Tehran');
INSERT INTO SourceTable (ID, Name, City) VALUES (2, 'Sara', 'Isfahan');
INSERT INTO SourceTable (ID, Name, City) VALUES (3, 'Reza', 'Shiraz');
INSERT INTO SourceTable (ID, Name, City) VALUES (4, 'Mona', 'Tehran');
سپس جدول TargetTable را ایجاد میکنیم. این جدول در ابتدا خالی خواهد بود:
CREATE TABLE TargetTable (
ID INT PRIMARY KEY,
Name VARCHAR(50),
City VARCHAR(50)
);
اکنون میتوانیم به سراغ مثالهای INSERT INTO SELECT برویم.
مثال 1: کپی کردن تمام ستونها از یک جدول
در این سناریو، تمام ستونها و ردیفها از SourceTable به TargetTable کپی میشوند. نکته مهم این است که تعداد و نوع داده ستونها در هر دو جدول باید یکسان باشد و ترتیب ستونها نیز باید مطابقت داشته باشد.
INSERT INTO TargetTable
SELECT *
FROM SourceTable;
برای مشاهده محتوای TargetTable پس از عملیات درج:
SELECT * FROM TargetTable;
خروجی به این صورت خواهد بود:
ID | Name | City
---|------|-------
1 | Ali | Tehran
2 | Sara | Isfahan
3 | Reza | Shiraz
4 | Mona | Tehran
مثال 2: کپی کردن ستونهای خاص
گاهی اوقات شما نیاز دارید که فقط ستونهای خاصی را از جدول منبع به جدول مقصد کپی کنید. در این حالت، باید نام ستونها را هم در بخش INSERT INTO و هم در بخش SELECT مشخص کنید.
ابتدا جدول TargetTable را خالی میکنیم تا نتایج مثالهای قبلی حذف شوند:
TRUNCATE TABLE TargetTable;
اکنون فقط ستونهای ID و Name را کپی میکنیم:
INSERT INTO TargetTable (ID, Name)
SELECT ID, Name
FROM SourceTable;
برای مشاهده محتوای TargetTable:
SELECT * FROM TargetTable;
خروجی نشان میدهد که ستون City در TargetTable خالی است (NULL)، زیرا مقداری برای آن درج نشده است:
ID | Name | City
---|------|-------
1 | Ali | NULL
2 | Sara | NULL
3 | Reza | NULL
4 | Mona | NULL
مثال 3: کپی کردن ردیفها بر اساس یک شرط
اگر بخواهید تنها زیرمجموعهای از ردیفها را از جدول منبع کپی کنید، میتوانید از بند WHERE در کوئری SELECT استفاده کنید. این به شما امکان میدهد تا دادهها را بر اساس معیارهای خاصی فیلتر کنید.
دوباره جدول TargetTable را خالی میکنیم:
TRUNCATE TABLE TargetTable;
اکنون فقط افرادی را که از شهر Tehran هستند، کپی میکنیم:
INSERT INTO TargetTable
SELECT ID, Name, City
FROM SourceTable
WHERE City = 'Tehran';
برای مشاهده محتوای TargetTable:
SELECT * FROM TargetTable;
خروجی نشان میدهد که فقط ردیفهای مربوط به Tehran کپی شدهاند:
ID | Name | City
---|------|-------
1 | Ali | Tehran
4 | Mona | Tehran
مثال 4: کپی کردن دادهها از یک پایگاه داده دیگر
شما میتوانید از دستور INSERT INTO SELECT برای کپی کردن دادهها بین جداول در پایگاههای داده مختلف در یک سرور SQL Server استفاده کنید. برای این کار، باید نام کامل جدول را شامل نام پایگاه داده و شمای آن (معمولاً dbo) مشخص کنید.
اجازه دهید یک پایگاه داده جدید به نام TestDB و یک جدول در آن ایجاد کنیم و سپس دادهها را به TargetTable در پایگاه داده فعلی خود کپی کنیم:
USE [master];
CREATE DATABASE [TestDB];
GO
USE [TestDB];
CREATE TABLE SourceTable_TestDB (
ID INT PRIMARY KEY,
Product VARCHAR(50),
Price DECIMAL(10, 2)
);
INSERT INTO SourceTable_TestDB (ID, Product, Price) VALUES (1, 'Laptop', 1200.00);
INSERT INTO SourceTable_TestDB (ID, Product, Price) VALUES (2, 'Mouse', 25.00);
INSERT INTO SourceTable_TestDB (ID, Product, Price) VALUES (3, 'Keyboard', 75.00);
GO
اکنون به پایگاه داده اصلی خود برمیگردیم و TargetTable را خالی میکنیم:
USE [YourCurrentDatabaseName]; -- نام پایگاه داده فعلی خود را اینجا قرار دهید
TRUNCATE TABLE TargetTable;
فرض میکنیم جدول TargetTable ما دارای ستونهای ID، Name و City است. ما باید مقادیر مناسب را از SourceTable_TestDB به آن نگاشت کنیم. فرض کنید میخواهیم Product را به Name و Price را به City نگاشت کنیم (که البته این نگاشت ممکن است منطقی نباشد، اما برای مثال به این شکل عمل میکنیم).
INSERT INTO TargetTable (ID, Name, City)
SELECT ID, Product, CAST(Price AS VARCHAR(50)) -- قیمت را به رشته تبدیل می کنیم تا در ستون City جا شود
FROM TestDB.dbo.SourceTable_TestDB;
نکته: در این مثال، ما نوع داده Price (DECIMAL) را به VARCHAR(50) تبدیل کردیم تا با نوع داده ستون City در TargetTable مطابقت داشته باشد. در سناریوهای واقعی، باید اطمینان حاصل کنید که انواع داده ستونهای مبدا و مقصد سازگار هستند.
برای مشاهده محتوای TargetTable:
SELECT * FROM TargetTable;
خروجی به این صورت خواهد بود:
ID | Name | City
---|----------|-------
1 | Laptop | 1200.00
2 | Mouse | 25.00
3 | Keyboard | 75.00
مثال 5: کپی کردن دادهها از یک سرور لینک شده (Linked Server)
برای کپی کردن دادهها از یک سرور SQL Server دیگر که به صورت “سرور لینک شده” پیکربندی شده است، میتوانید از نام چهاربخشی (Four-Part Name) استفاده کنید: LinkedServerName.DatabaseName.SchemaName.TableName.
ابتدا، یک سرور لینک شده (Linked Server) ایجاد میکنیم. این عملیات نیاز به مجوزهای مدیریتی دارد و باید نام سرور مقصد را بدانید. (برای مثال YourLinkedServer را به نام سرور لینک شده خود تغییر دهید و TargetServerName را با نام واقعی سرور مقصد جایگزین کنید).
EXEC sp_addlinkedserver
@server = N'YourLinkedServer', -- نامی که به سرور لینک شده خود می دهید
@srvproduct = N'SQL Server';
EXEC sp_addlinkedsrvlogin
@rmtsrvname = N'YourLinkedServer',
@useself = N'FALSE',
@locallogin = NULL, -- همه کاربران محلی
@rmtuser = N'RemoteUser', -- نام کاربری در سرور مقصد
@rmtpassword = N'RemotePassword'; -- رمز عبور در سرور مقصد
GO
پس از ایجاد سرور لینک شده، میتوانیم از آن برای کپی کردن دادهها استفاده کنیم. فرض کنید در سرور لینک شده YourLinkedServer، در پایگاه داده RemoteDB و شمای dbo، جدولی به نام RemoteSourceTable داریم که دارای ستونهای RemoteID، RemoteName و RemoteValue است.
دوباره TargetTable را خالی میکنیم:
TRUNCATE TABLE TargetTable;
اکنون دادهها را از RemoteSourceTable در سرور لینک شده به TargetTable کپی میکنیم:
INSERT INTO TargetTable (ID, Name, City)
SELECT RemoteID, RemoteName, CAST(RemoteValue AS VARCHAR(50))
FROM YourLinkedServer.RemoteDB.dbo.RemoteSourceTable;
همچنین میتوانید از OPENROWSET استفاده کنید که نیازی به پیکربندی دائمی سرور لینک شده ندارد و برای کوئریهای یکباره مناسب است. در این حالت، شما مستقیماً نام سرور و اعتبارنامههای لازم را در کوئری مشخص میکنید. این روش به ویژه برای منابع دادهای که به ندرت به آنها دسترسی پیدا میکنید یا برای اسکریپتهای موقت مفید است.
-- مثال با استفاده از OPENROWSET
TRUNCATE TABLE TargetTable;
INSERT INTO TargetTable (ID, Name, City)
SELECT ID, Name, City
FROM OPENROWSET('SQLNCLI', 'Server=YourRemoteServerName;UID=RemoteUser;PWD=RemotePassword;',
'SELECT ID, Name, City FROM RemoteDB.dbo.RemoteSourceTable');
توجه: استفاده از OPENROWSET نیازمند فعال بودن گزینه Ad Hoc Distributed Queries در تنظیمات SQL Server است. همچنین، امنیت این روش به دلیل قرار گرفتن رمز عبور در متن کوئری باید با احتیاط مدیریت شود.
برای مشاهده محتوای TargetTable:
SELECT * FROM TargetTable;
خروجی بسته به دادههای موجود در RemoteSourceTable خواهد بود.