مثال هایی از راهنمای جامع دستورات T-SQL در SQL Server

راهنمای جامع دستورات T-SQL در SQL Server با مثال

توسط admin | گروه SQL Server | 1405/05/11

نظرات 0

راهنمای جامع دستورات T-SQL در SQL Server؛ Cheat Sheet کاربردی 2026

این راهنما یک مرجع سریع و کاربردی برای مهم‌ترین دستورات T-SQL در Microsoft SQL Server است. مطالب بر اساس ساختار صفحه «SQL Server Cheat Sheet» منتشرشده در سال 2026 تنظیم شده‌اند و از عملیات پایه CRUD تا JOINها، CTE، Window Functions، مدیریت Table، Index و ابزارهای Query Tuning را پوشش می‌دهند.

توضیحات به زبان فارسی نوشته شده‌اند، اما نام دستورها، توابع، Keywordها، Data Typeها و سایر اصطلاحات مرتبط با SQL بدون ترجمه باقی مانده‌اند تا بتوانید مثال‌ها را مستقیماً در SQL Server Management Studio یا محیط‌های مشابه اجرا و ویرایش کنید.

در این Cheat Sheet چه چیزهایی یاد می‌گیرید؟

  • خواندن، درج، ویرایش و حذف داده با SELECT، INSERT، UPDATE و DELETE
  • فیلتر کردن، مرتب‌سازی و Pagination با WHERE، TOP و OFFSET FETCH
  • گروه‌بندی و محاسبات آماری با Aggregate Functions
  • ترکیب Tableها با انواع JOIN و APPLY
  • ساخت Queryهای پیشرفته با Subquery، CTE و Window Functions
  • کار با قابلیت‌های اختصاصی SQL Server مانند IDENTITY، OUTPUT و TRY_CAST
  • مدیریت Table، Index، Query Store و Execution Plan

تفاوت SQL و T-SQL چیست؟

SQL زبان استاندارد کار با پایگاه داده‌های رابطه‌ای است. T-SQL یا Transact-SQL توسعه مایکروسافت بر SQL استاندارد محسوب می‌شود و در SQL Server و Azure SQL Database استفاده می‌شود.

علاوه بر قابلیت‌های استاندارد SQL، در T-SQL دستورها و توابع اختصاصی مانند TOP، TRY_CAST، IIF، CHOOSE، OUTPUT، CROSS APPLY، Temp Table، Table Variable و ساختارهای کنترلی وجود دارند.

دستورات پایه CRUD

چهار عملیات اصلی روی داده‌ها شامل خواندن، درج، ویرایش و حذف است. این عملیات با دستورهای SELECT، INSERT، UPDATE و DELETE انجام می‌شوند.

SELECT برای خواندن داده

با SELECT می‌توانید یک یا چند Column را از یک Table دریافت کنید. استفاده از نام Columnها معمولاً خواناتر و کنترل‌شده‌تر از SELECT * است.

-- Select specific columns SELECT first_name, last_name, email FROM customers;  -- Select all columns SELECT * FROM products;  -- Use aliases SELECT first_name AS display_name,        email AS contact_email FROM customers;

INSERT INTO برای افزودن Row جدید

INSERT INTO برای درج یک Row، چند Row یا انتقال نتیجه یک SELECT به Table دیگر استفاده می‌شود.

-- Insert one row INSERT INTO customers (first_name, last_name, email) VALUES ('Sara', 'Ahmadi', 'sara@example.com');  -- Insert multiple rows INSERT INTO products (product_name, category, price) VALUES     ('Keyboard', 'hardware', 85.00),     ('Monitor', 'hardware', 420.00);  -- Insert rows returned by another query INSERT INTO archived_orders (order_id, customer_id, total_amount) SELECT order_id, customer_id, total_amount FROM orders WHERE order_date < '2025-01-01';

UPDATE برای تغییر داده‌های موجود

دستور UPDATE Rowهای موجود را تغییر می‌دهد. وجود شرط WHERE تعیین می‌کند کدام Rowها ویرایش شوند.

-- Update one customer UPDATE customers SET email = 'new-address@example.com' WHERE customer_id = 42;  -- Update several columns UPDATE products SET price = price * 1.10,     updated_at = GETDATE() WHERE category = 'hardware';

نکته مهم: اجرای UPDATE بدون WHERE تمام Rowهای Table را تغییر می‌دهد. پیش از اجرای نهایی، شرط را با یک SELECT آزمایش کنید.

DELETE برای حذف Rowها

DELETE Rowهای انتخاب‌شده را حذف می‌کند. با حذف شرط WHERE، تمام Rowهای Table حذف می‌شوند، اما ساختار Table باقی می‌ماند.

-- Delete selected rows DELETE FROM orders WHERE status = 'cancelled'   AND created_at < '2025-01-01';  -- Delete every row while keeping the table DELETE FROM temporary_logs;

MERGE برای ترکیب INSERT، UPDATE و DELETE

MERGE یک دستور اختصاصی SQL Server است که Source و Target را مقایسه می‌کند و بر اساس وضعیت Match، عملیات موردنیاز را انجام می‌دهد.

MERGE INTO inventory AS target USING staging_inventory AS source ON target.sku = source.sku WHEN MATCHED THEN     UPDATE SET         target.quantity = source.quantity,         target.updated_at = GETDATE() WHEN NOT MATCHED BY TARGET THEN     INSERT (sku, product_name, quantity, created_at)     VALUES (source.sku, source.product_name, source.quantity, GETDATE()) WHEN NOT MATCHED BY SOURCE THEN     DELETE;

فیلتر کردن و مرتب‌سازی داده‌ها

فیلترها مشخص می‌کنند چه Rowهایی در نتیجه نمایش داده شوند. مرتب‌سازی نیز ترتیب نمایش نتیجه را کنترل می‌کند.

WHERE، AND و OR

SELECT * FROM orders WHERE status = 'shipped'   AND total_amount > 100   AND (region = 'EU' OR region = 'ME');

IN و BETWEEN

IN مقدار را با یک List مقایسه می‌کند. BETWEEN برای محدوده Inclusive به‌کار می‌رود؛ یعنی ابتدا و انتهای محدوده نیز در نتیجه قرار می‌گیرند.

SELECT * FROM products WHERE category IN ('hardware', 'software', 'books');  SELECT * FROM orders WHERE order_date BETWEEN '2026-01-01' AND '2026-03-31';

LIKE برای Pattern Matching

  • % هر تعداد Character را Match می‌کند.
  • _ دقیقاً یک Character را Match می‌کند.
SELECT * FROM customers WHERE email LIKE '%@example.com';  SELECT * FROM products WHERE sku LIKE 'PRD-____';

IS NULL و IS NOT NULL

برای بررسی مقدارهای NULL نباید از عملگر مساوی استفاده کرد. از IS NULL و IS NOT NULL استفاده کنید.

SELECT * FROM customers WHERE phone IS NULL;  SELECT * FROM customers WHERE phone IS NOT NULL;

ORDER BY، TOP و Pagination

در SQL Server برای محدود کردن تعداد Rowها از TOP استفاده می‌شود. Keyword رایج LIMIT در SQL Server پشتیبانی نمی‌شود. برای Pagination نیز می‌توان از OFFSET و FETCH NEXT استفاده کرد.

-- First 10 rows after sorting SELECT TOP 10 product_name, price FROM products ORDER BY price DESC;  -- Top 5 percent SELECT TOP 5 PERCENT * FROM orders ORDER BY total_amount DESC;  -- Page 3 with 20 rows per page SELECT * FROM customers ORDER BY created_at DESC OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;

توجه: برای نتیجه قابل پیش‌بینی، TOP را همراه ORDER BY استفاده کنید. در مقابل، OFFSET FETCH به ORDER BY نیاز دارد.

Aggregation و گروه‌بندی

Aggregate Functions مجموعه‌ای از Rowها را خلاصه می‌کنند و خروجی‌هایی مانند تعداد، مجموع، میانگین، کمترین و بیشترین مقدار می‌سازند.

COUNT، SUM، AVG، MIN و MAX

SELECT     COUNT(*) AS total_orders,     SUM(total_amount) AS total_revenue,     AVG(total_amount) AS average_order_value,     MIN(total_amount) AS smallest_order,     MAX(total_amount) AS largest_order FROM orders WHERE order_date >= '2026-01-01';

GROUP BY

GROUP BY Rowهای دارای مقدار مشترک را در یک Group قرار می‌دهد تا Aggregate Function روی هر Group جداگانه اجرا شود.

SELECT     category,     COUNT(*) AS product_count,     SUM(price) AS inventory_value FROM products GROUP BY category ORDER BY inventory_value DESC;

HAVING برای فیلتر Groupها

WHERE پیش از Grouping روی Rowها اعمال می‌شود، اما HAVING پس از Grouping روی نتیجه Aggregate اعمال می‌شود.

SELECT category, COUNT(*) AS product_count FROM products GROUP BY category HAVING COUNT(*) > 10 ORDER BY product_count DESC;
Keyword زمان اعمال کاربرد
WHERE پیش از GROUP BY فیلتر کردن Rowهای اولیه
HAVING پس از GROUP BY فیلتر کردن Groupها و Aggregate Result

STRING_AGG برای ترکیب Stringها

STRING_AGG مقدارهای String را با یک Separator در کنار هم قرار می‌دهد و از SQL Server 2017 در دسترس است.

SELECT     department,     STRING_AGG(employee_name, ', ')         WITHIN GROUP (ORDER BY hire_date) AS team_members FROM employees GROUP BY department;

انواع JOIN در SQL Server

JOIN برای ترکیب Rowهای دو یا چند Table بر اساس یک رابطه مشترک استفاده می‌شود.

نوع رفتار کاربرد رایج
INNER JOIN فقط Rowهای Match‌شده در هر دو Table نمایش داده‌هایی که رابطه معتبر دارند
LEFT JOIN تمام Rowهای Table سمت چپ و Matchهای سمت راست نمایش همه رکوردهای اصلی حتی بدون رابطه
RIGHT JOIN تمام Rowهای Table سمت راست و Matchهای سمت چپ حفظ کامل داده‌های Table سمت راست
FULL OUTER JOIN تمام Rowهای هر دو Table مقایسه کامل دو مجموعه داده
CROSS JOIN تمام ترکیب‌های ممکن ساخت Matrix یا Combination
CROSS APPLY اجرای Subquery مرتبط برای هر Row؛ رفتار شبیه INNER JOIN Top N برای هر Parent
OUTER APPLY مانند CROSS APPLY اما Parent بدون نتیجه را نیز نگه می‌دارد رفتار شبیه LEFT JOIN

INNER JOIN

SELECT o.order_id,        o.order_date,        c.customer_name,        c.email FROM orders AS o INNER JOIN customers AS c     ON o.customer_id = c.customer_id;

LEFT JOIN

SELECT c.customer_name,        COUNT(o.order_id) AS order_count FROM customers AS c LEFT JOIN orders AS o     ON c.customer_id = o.customer_id GROUP BY c.customer_name;

RIGHT JOIN

SELECT p.product_name,        SUM(oi.quantity) AS total_sold FROM order_items AS oi RIGHT JOIN products AS p     ON oi.product_id = p.product_id GROUP BY p.product_name;

FULL OUTER JOIN

SELECT c.customer_name,        o.order_id FROM customers AS c FULL OUTER JOIN orders AS o     ON c.customer_id = o.customer_id;

CROSS JOIN

SELECT s.size_name,        c.color_name FROM sizes AS s CROSS JOIN colors AS c;

CROSS APPLY و OUTER APPLY

CROSS APPLY و OUTER APPLY امکان اجرای یک Correlated Subquery یا Table-Valued Function را برای هر Row از Query بیرونی فراهم می‌کنند.

-- Top 3 orders for every customer SELECT c.customer_name,        x.order_id,        x.total_amount FROM customers AS c CROSS APPLY (     SELECT TOP 3 order_id, total_amount     FROM orders     WHERE customer_id = c.customer_id     ORDER BY total_amount DESC ) AS x;  -- Latest order while keeping customers with no orders SELECT c.customer_name,        x.order_id,        x.order_date FROM customers AS c OUTER APPLY (     SELECT TOP 1 order_id, order_date     FROM orders     WHERE customer_id = c.customer_id     ORDER BY order_date DESC ) AS x;

Subquery و CTE

Subquery و CTE برای تقسیم Queryهای پیچیده به بخش‌های قابل مدیریت استفاده می‌شوند.

Scalar Subquery

Scalar Subquery باید یک مقدار واحد برگرداند و می‌تواند در بخش SELECT یا شرط‌ها استفاده شود.

SELECT product_name,        price,        price - (SELECT AVG(price) FROM products) AS difference_from_average FROM products;

Subquery همراه IN

SELECT customer_name, email FROM customers WHERE customer_id IN (     SELECT customer_id     FROM orders     WHERE total_amount > 500 );

EXISTS

EXISTS بررسی می‌کند که Subquery حداقل یک Row برمی‌گرداند یا خیر.

SELECT p.product_name FROM products AS p WHERE EXISTS (     SELECT 1     FROM order_items AS oi     WHERE oi.product_id = p.product_id );

CTE با WITH

CTE یک Result Set نام‌گذاری‌شده و موقت برای Query جاری ایجاد می‌کند.

WITH monthly_revenue AS (     SELECT         DATEFROMPARTS(YEAR(order_date), MONTH(order_date), 1) AS revenue_month,         SUM(total_amount) AS revenue     FROM orders     GROUP BY YEAR(order_date), MONTH(order_date) ) SELECT revenue_month,        revenue,        SUM(revenue) OVER (ORDER BY revenue_month) AS running_total FROM monthly_revenue ORDER BY revenue_month;

Recursive CTE

Recursive CTE برای داده‌های سلسله‌مراتبی مانند ساختار سازمانی، دسته‌بندی‌های Parent/Child و مسیرها کاربرد دارد.

WITH organization AS (     SELECT employee_id,            employee_name,            manager_id,            0 AS hierarchy_level     FROM employees     WHERE manager_id IS NULL      UNION ALL      SELECT e.employee_id,            e.employee_name,            e.manager_id,            o.hierarchy_level + 1     FROM employees AS e     INNER JOIN organization AS o         ON e.manager_id = o.employee_id ) SELECT employee_id,        employee_name,        hierarchy_level FROM organization ORDER BY hierarchy_level, employee_name;

Window Functions

Window Functions روی مجموعه‌ای از Rowهای مرتبط با Row جاری محاسبه انجام می‌دهند، بدون آن‌که Rowها را مانند GROUP BY به یک Row خلاصه کنند.

ROW_NUMBER، RANK، DENSE_RANK و NTILE

SELECT employee_name,        department,        salary,        ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_number_value,        RANK() OVER (ORDER BY salary DESC) AS rank_value,        DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank_value,        NTILE(4) OVER (ORDER BY salary DESC) AS salary_quartile FROM employees;
Function رفتار
ROW_NUMBER() شماره یکتای متوالی برای هر Row ایجاد می‌کند.
RANK() برای مقدارهای برابر Rank یکسان می‌دهد و پس از Tie فاصله ایجاد می‌کند؛ مانند 1، 2، 2، 4.
DENSE_RANK() برای Tie مقدار یکسان می‌دهد اما فاصله ایجاد نمی‌کند؛ مانند 1، 2، 2، 3.
NTILE(n) Rowها را به تعداد Group مشخص تقسیم می‌کند.

PARTITION BY

PARTITION BY Window را به بخش‌های مستقل تقسیم می‌کند. مثال زیر کارکنان را داخل هر Department رتبه‌بندی می‌کند.

SELECT employee_name,        department,        salary,        RANK() OVER (            PARTITION BY department            ORDER BY salary DESC        ) AS department_rank FROM employees;

LAG و LEAD

LAG مقدار Row قبلی و LEAD مقدار Row بعدی را در Window برمی‌گرداند.

SELECT revenue_month,        revenue,        LAG(revenue, 1) OVER (ORDER BY revenue_month) AS previous_month,        LEAD(revenue, 1) OVER (ORDER BY revenue_month) AS next_month,        revenue - LAG(revenue, 1) OVER (ORDER BY revenue_month) AS month_change FROM monthly_revenue;

Running Total و Moving Average

-- Running total SELECT order_date,        total_amount,        SUM(total_amount) OVER (            ORDER BY order_date            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW        ) AS running_total FROM orders;  -- 7-row moving average SELECT sales_date,        daily_revenue,        AVG(daily_revenue) OVER (            ORDER BY sales_date            ROWS BETWEEN 6 PRECEDING AND CURRENT ROW        ) AS moving_average_7 FROM daily_sales;

قابلیت‌های اختصاصی SQL Server

IDENTITY و SCOPE_IDENTITY

IDENTITY(seed, increment) برای تولید مقدار Auto-Increment استفاده می‌شود. برای دریافت آخرین Identity ثبت‌شده در Scope جاری، SCOPE_IDENTITY() انتخاب مناسب‌تری نسبت به @@IDENTITY است، زیرا @@IDENTITY ممکن است مقدار درج‌شده توسط Trigger را برگرداند.

CREATE TABLE app_users (     user_id INT IDENTITY(1,1) PRIMARY KEY,     user_name NVARCHAR(100) NOT NULL,     email NVARCHAR(255) NOT NULL );  INSERT INTO app_users (user_name, email) VALUES (N'Sara', N'sara@example.com');  SELECT SCOPE_IDENTITY() AS new_user_id;

ISNULL و COALESCE

  • ISNULL مختص SQL Server است و دقیقاً دو Argument دریافت می‌کند.
  • COALESCE بخشی از SQL استاندارد است و اولین مقدار Non-NULL را از چند Argument برمی‌گرداند.
SELECT ISNULL(phone, 'N/A') AS phone FROM customers;  SELECT COALESCE(mobile_phone, work_phone, home_phone, 'N/A') AS contact_number FROM customers;

TOP WITH TIES

WITH TIES علاوه بر N Row اول، Rowهایی را که در آخرین جایگاه مقدار برابر دارند نیز برمی‌گرداند.

SELECT TOP 5 WITH TIES product_name, price FROM products ORDER BY price DESC;

OUTPUT Clause

OUTPUT امکان مشاهده Rowهای درج‌شده، حذف‌شده یا مقدارهای پیش و پس از Update را فراهم می‌کند.

-- Return inserted values INSERT INTO app_users (user_name, email) OUTPUT INSERTED.user_id, INSERTED.user_name, INSERTED.email VALUES (N'Ali', N'ali@example.com');  -- Return deleted values DELETE FROM orders OUTPUT DELETED.order_id, DELETED.customer_id, DELETED.total_amount WHERE status = 'cancelled';  -- Return old and new values UPDATE products SET price = price * 1.10 OUTPUT     DELETED.price AS old_price,     INSERTED.price AS new_price,     INSERTED.product_id WHERE category = 'hardware';

TRY_CAST و TRY_CONVERT

در صورت نامعتبر بودن Conversion، این توابع به‌جای ایجاد Error مقدار NULL برمی‌گردانند.

SELECT TRY_CAST('abc' AS INT) AS invalid_integer; SELECT TRY_CAST('123' AS INT) AS valid_integer;  SELECT TRY_CONVERT(DATE, '2026-13-01') AS invalid_date; SELECT TRY_CONVERT(DATE, '2026-03-12') AS valid_date;

IIF و CHOOSE

SELECT employee_name,        salary,        IIF(salary > 100000, 'Senior', 'Standard') AS salary_band FROM employees;  SELECT order_id,        CHOOSE(            MONTH(order_date),            'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'        ) AS order_month FROM orders;

Temp Table و Table Variable

SQL Server سه الگوی رایج برای داده موقت دارد: Local Temp Table، Global Temp Table و Table Variable.

-- Local temp table: current session CREATE TABLE #recent_orders (     order_id INT,     customer_id INT,     total_amount DECIMAL(12,2) );  INSERT INTO #recent_orders SELECT order_id, customer_id, total_amount FROM orders WHERE order_date >= '2026-01-01';  -- Global temp table: visible to sessions while it exists CREATE TABLE ##shared_cache (     cache_key NVARCHAR(100),     cache_value NVARCHAR(MAX) );  -- Table variable: current batch or procedure scope DECLARE @top_customers TABLE (     customer_id INT,     total_spent DECIMAL(12,2) );  INSERT INTO @top_customers SELECT TOP 100 customer_id, SUM(total_amount) FROM orders GROUP BY customer_id ORDER BY SUM(total_amount) DESC;  SELECT * FROM @top_customers;
ساختار Scope Syntax
Local Temp Table Session جاری #table_name
Global Temp Table Sessionهای مختلف تا زمان موجود بودن Object ##table_name
Table Variable Batch، Function یا Stored Procedure جاری @table_name

NEWID برای UNIQUEIDENTIFIER

SELECT NEWID() AS generated_id;  CREATE TABLE user_sessions (     session_id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,     user_id INT NOT NULL,     created_at DATETIME2 DEFAULT SYSDATETIME() );

توابع String در T-SQL

توابع String برای ترکیب، برش، پاک‌سازی، جست‌وجو، جایگزینی و Format کردن متن استفاده می‌شوند.

-- CONCAT is NULL-safe SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM customers;  -- + operator propagates NULL SELECT first_name + ' ' + last_name AS full_name FROM customers;  -- Extract part of a string; position is 1-based SELECT SUBSTRING(phone, 1, 3) AS area_code FROM contacts;  -- Remove spaces SELECT TRIM(product_name) FROM products; SELECT LTRIM(RTRIM(product_name)) FROM products;  -- Change letter case SELECT UPPER(email) FROM customers; SELECT LOWER(city) FROM addresses;  -- String length, excluding trailing spaces SELECT product_name, LEN(product_name) AS name_length FROM products;  -- Replace text SELECT REPLACE(url, 'http://', 'https://') AS secure_url FROM links;  -- Find substring position; 0 means not found SELECT CHARINDEX('@', email) AS at_position FROM customers;  -- Delete and insert at a position SELECT STUFF('SQL Server', 5, 6, 'Database') AS changed_text;  -- Combine grouped values SELECT department, STRING_AGG(employee_name, ', ') AS members FROM employees GROUP BY department;  -- Locale-aware formatting SELECT FORMAT(price, 'C', 'en-US') AS formatted_price FROM products;

نکته نسخه: TRIM و STRING_AGG در SQL Server 2017 و نسخه‌های جدیدتر در دسترس هستند. برای نسخه‌های قدیمی‌تر می‌توان از ترکیب LTRIM و RTRIM برای حذف فاصله ابتدا و انتهای String استفاده کرد.

توابع Date و Time

توابع Date و Time در T-SQL برای دریافت زمان جاری، افزودن Interval، محاسبه اختلاف، استخراج Date Part، Format و ساخت Date استفاده می‌شوند.

-- Current date and time SELECT GETDATE(); SELECT SYSDATETIME(); SELECT GETUTCDATE();  -- Add or subtract intervals SELECT DATEADD(DAY, 7, order_date) AS one_week_later FROM orders;  SELECT DATEADD(MONTH, -3, GETDATE()) AS three_months_ago;  -- Difference between dates SELECT DATEDIFF(DAY, ship_date, delivery_date) AS transit_days FROM shipments;  -- Extract date parts SELECT DATEPART(WEEKDAY, order_date) AS weekday_number,        DATEPART(QUARTER, order_date) AS quarter_number FROM orders;  SELECT YEAR(order_date) AS order_year,        MONTH(order_date) AS order_month,        DAY(order_date) AS order_day FROM orders;  -- Format date values SELECT FORMAT(order_date, 'yyyy-MM-dd') AS iso_date FROM orders;  -- CONVERT style codes SELECT CONVERT(VARCHAR, GETDATE(), 23) AS iso_date; SELECT CONVERT(VARCHAR, GETDATE(), 101) AS us_date; SELECT CONVERT(VARCHAR, GETDATE(), 108) AS time_value;  -- End of month SELECT EOMONTH(GETDATE()) AS current_month_end; SELECT EOMONTH(GETDATE(), -1) AS previous_month_end; SELECT EOMONTH(GETDATE(), 2) AS future_month_end;  -- Build values from parts SELECT DATEFROMPARTS(2026, 3, 12) AS created_date; SELECT DATETIME2FROMPARTS(2026, 3, 12, 14, 30, 0, 0, 0) AS created_datetime;  -- Last 30 days SELECT * FROM orders WHERE order_date >= DATEADD(DAY, -30, GETDATE());
Function خروجی یا کاربرد
GETDATE() تاریخ و زمان جاری با Data Type از نوع DATETIME
SYSDATETIME() تاریخ و زمان جاری با Data Type از نوع DATETIME2 و Precision بالاتر
GETUTCDATE() تاریخ و زمان جاری بر اساس UTC
DATEADD() افزودن یا کم‌کردن Interval
DATEDIFF() محاسبه اختلاف دو Date بر اساس Date Part تعیین‌شده
DATEPART() استخراج بخش خاصی از Date به‌صورت Integer
EOMONTH() دریافت آخرین روز ماه
DATEFROMPARTS() ساخت مقدار DATE از Year، Month و Day

عملیات مربوط به Table

CREATE TABLE

CREATE TABLE customers (     customer_id INT IDENTITY(1,1) PRIMARY KEY,     first_name NVARCHAR(100) NOT NULL,     last_name NVARCHAR(100) NOT NULL,     email NVARCHAR(255) UNIQUE NOT NULL,     created_at DATETIME2 DEFAULT SYSDATETIME(),     is_active BIT DEFAULT 1 );

ALTER TABLE

-- Add a column ALTER TABLE customers ADD phone NVARCHAR(20);  -- Change a column definition ALTER TABLE products ALTER COLUMN price DECIMAL(12,2) NOT NULL;  -- Add a foreign key ALTER TABLE orders ADD CONSTRAINT fk_orders_customers     FOREIGN KEY (customer_id)     REFERENCES customers(customer_id);  -- Add a default constraint ALTER TABLE customers ADD CONSTRAINT df_customers_status     DEFAULT 'active' FOR status;  -- Drop a column ALTER TABLE customers DROP COLUMN phone;

DROP TABLE

-- SQL Server 2016+ DROP TABLE IF EXISTS import_staging;  -- Older versions IF OBJECT_ID('import_staging', 'U') IS NOT NULL     DROP TABLE import_staging;

CREATE INDEX و DROP INDEX

-- Nonclustered index CREATE NONCLUSTERED INDEX idx_customers_email ON customers(email);  -- Composite index CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);  -- Unique index CREATE UNIQUE INDEX idx_customers_email_unique ON customers(email);  -- Clustered index CREATE CLUSTERED INDEX idx_orders_date ON orders(order_date);  -- Covering index with included columns CREATE INDEX idx_orders_status ON orders(status) INCLUDE (customer_id, total_amount);  -- Drop an index DROP INDEX idx_customers_email ON customers;

TRUNCATE TABLE

TRUNCATE TABLE تمام Rowها را حذف می‌کند و Identity را Reset می‌کند. این دستور برای حذف کامل داده‌های Table با حفظ ساختار استفاده می‌شود.

TRUNCATE TABLE temporary_logs;

بررسی ساختار Table با sp_help و sp_columns

EXEC sp_help 'customers'; EXEC sp_columns 'customers';

Query Tuning و بررسی Performance

SET STATISTICS IO و SET STATISTICS TIME

این تنظیمات اطلاعات Logical Read، CPU Time و Elapsed Time را در بخش Messages نمایش می‌دهند.

SET STATISTICS IO ON; SET STATISTICS TIME ON;  SELECT c.customer_name,        COUNT(o.order_id) AS order_count FROM customers AS c INNER JOIN orders AS o     ON c.customer_id = o.customer_id GROUP BY c.customer_name;  SET STATISTICS IO OFF; SET STATISTICS TIME OFF;

Estimated و Actual Execution Plan

Estimated Plan بدون اجرای Query، Plan تخمینی را ارائه می‌کند. Actual Plan Query را اجرا می‌کند و اطلاعات واقعی مانند تعداد Rowها را نشان می‌دهد.

-- Estimated plan SET SHOWPLAN_XML ON; GO SELECT * FROM orders WHERE customer_id = 42; GO SET SHOWPLAN_XML OFF;  -- Actual plan SET STATISTICS XML ON; SELECT * FROM orders WHERE customer_id = 42; SET STATISTICS XML OFF;

در SSMS می‌توانید از Ctrl+L برای Estimated Plan و Ctrl+M برای فعال کردن Actual Plan استفاده کنید.

انواع Index در یک نگاه

Index Type ویژگی اصلی کاربرد
Clustered Index ترتیب فیزیکی Rowها را تعیین می‌کند و هر Table فقط یک مورد دارد. اغلب برای Primary Key یا Column اصلی مرتب‌سازی
Nonclustered Index ساختاری جداگانه برای اشاره به Rowها ایجاد می‌کند و هر Table می‌تواند چند مورد داشته باشد. Columnهای استفاده‌شده در WHERE، JOIN و ORDER BY
Columnstore Index داده را به‌صورت Column-Based ذخیره می‌کند و Compression بالایی دارد. Analytics و Aggregation روی Tableهای بزرگ
Filtered Index فقط بخشی از داده‌ها را با شرط WHERE Index می‌کند. داده‌های Partial مانند Rowهای Active

Query Store

Query Store برای نگهداری History مربوط به Query، Plan و Runtime Statistics استفاده می‌شود.

ALTER DATABASE SalesDatabase SET QUERY_STORE = ON;  SELECT TOP 10     qt.query_sql_text,     rs.avg_duration,     rs.avg_logical_io_reads,     rs.count_executions FROM sys.query_store_query_text AS qt INNER JOIN sys.query_store_query AS q     ON qt.query_text_id = q.query_text_id INNER JOIN sys.query_store_plan AS p     ON q.query_id = p.query_id INNER JOIN sys.query_store_runtime_stats AS rs     ON p.plan_id = rs.plan_id ORDER BY rs.avg_duration DESC;

Dynamic SQL با sp_executesql

در Dynamic SQL، استفاده از Parameter به‌جای اتصال مستقیم مقدارها به String، Query را قابل کنترل‌تر می‌کند و از الگوی Parameterized Query پیروی می‌کند.

DECLARE @sql NVARCHAR(MAX); DECLARE @category NVARCHAR(50) = N'hardware'; DECLARE @min_price DECIMAL(12,2) = 100;  SET @sql = N' SELECT product_name, price FROM products WHERE category = @category_parameter   AND price >= @price_parameter ORDER BY price DESC';  EXEC sp_executesql     @sql,     N'@category_parameter NVARCHAR(50), @price_parameter DECIMAL(12,2)',     @category_parameter = @category,     @price_parameter = @min_price;

اشتباهات رایج

  1. اجرای UPDATE یا DELETE بدون WHERE: این کار تمام Rowهای Table را تحت تأثیر قرار می‌دهد.
  2. استفاده از LIMIT در SQL Server: برای محدود کردن نتیجه باید از TOP یا OFFSET FETCH استفاده شود.
  3. مقایسه NULL با علامت مساوی: عبارت‌هایی مانند phone = NULL درست نیستند؛ از IS NULL استفاده کنید.
  4. استفاده از Aggregate Function در WHERE: شرط Aggregate معمولاً باید در HAVING قرار گیرد.
  5. استفاده از @@IDENTITY بدون توجه به Trigger: برای Scope جاری، SCOPE_IDENTITY() یا OUTPUT INSERTED مناسب‌تر است.
  6. Pagination بدون ترتیب مشخص: OFFSET FETCH به ORDER BY نیاز دارد.
  7. استفاده نادرست از RIGHT JOIN: در بسیاری از Queryها می‌توان با جابه‌جایی ترتیب Tableها و استفاده از LEFT JOIN خوانایی را بیشتر کرد؛ اما رفتار اصلی هر دو باید به‌درستی درک شود.
  8. نادیده گرفتن Execution Plan: Query صحیح ممکن است روی داده زیاد کند باشد؛ Plan و Statistics به شناسایی Bottleneck کمک می‌کنند.

بهترین روش‌ها

  • به‌جای SELECT * فقط Columnهای موردنیاز را انتخاب کنید.
  • پیش از اجرای دستورهای تغییردهنده، شرط WHERE را با SELECT بررسی کنید.
  • برای Result Set محدود، TOP را همراه ORDER BY بنویسید.
  • برای داده فارسی یا Unicode از Data Typeهای NCHAR و NVARCHAR و در Literalها از پیشوند N استفاده کنید.
  • در Dynamic SQL از sp_executesql و Parameter استفاده کنید.
  • Index را بر اساس الگوی واقعی WHERE، JOIN و ORDER BY طراحی کنید.
  • برای Queryهای سنگین، SET STATISTICS IO، SET STATISTICS TIME و Execution Plan را بررسی کنید.
  • تفاوت WHERE و HAVING، و همچنین تفاوت ROW_NUMBER، RANK و DENSE_RANK را در Queryهای تحلیلی در نظر بگیرید.
  • برای Conversionهای ورودی نامطمئن، TRY_CAST یا TRY_CONVERT را به‌کار ببرید.

مثال عملی یک Query گزارش‌گیری

در سناریوی زیر، درآمد ماهانه هر Customer محاسبه می‌شود، تنها Customerهایی که مجموع خریدشان بیش از 1000 است باقی می‌مانند و رتبه آن‌ها داخل هر Month تعیین می‌شود.

WITH customer_monthly_sales AS (     SELECT         DATEFROMPARTS(YEAR(o.order_date), MONTH(o.order_date), 1) AS sales_month,         c.customer_id,         c.customer_name,         COUNT(o.order_id) AS order_count,         SUM(o.total_amount) AS total_revenue     FROM customers AS c     INNER JOIN orders AS o         ON c.customer_id = o.customer_id     WHERE o.status = 'completed'       AND o.order_date >= '2026-01-01'     GROUP BY         YEAR(o.order_date),         MONTH(o.order_date),         c.customer_id,         c.customer_name     HAVING SUM(o.total_amount) > 1000 ) SELECT     sales_month,     customer_id,     customer_name,     order_count,     total_revenue,     DENSE_RANK() OVER (         PARTITION BY sales_month         ORDER BY total_revenue DESC     ) AS revenue_rank FROM customer_monthly_sales ORDER BY sales_month, revenue_rank, customer_name;

پرسش‌های متداول

برای محدود کردن نتیجه در SQL Server از چه دستوری استفاده می‌شود؟

از TOP N برای دریافت N Row اول استفاده می‌شود. برای Pagination می‌توان از ORDER BY ... OFFSET ... FETCH NEXT استفاده کرد.

CROSS APPLY چه تفاوتی با INNER JOIN دارد؟

CROSS APPLY می‌تواند برای هر Row از Query بیرونی یک Correlated Subquery یا Table-Valued Function را اجرا کند و به Columnهای همان Row دسترسی داشته باشد. نتیجه آن از نظر حفظ Rowها شبیه رفتار INNER JOIN است. OUTER APPLY Rowهای بدون Match را نیز نگه می‌دارد.

شناسه Row تازه درج‌شده را چگونه دریافت کنیم؟

برای Columnهای IDENTITY می‌توان از SCOPE_IDENTITY() استفاده کرد. راه دیگر استفاده از OUTPUT INSERTED.column_name در همان دستور INSERT است.

تفاوت WHERE و HAVING چیست؟

WHERE Rowهای اولیه را پیش از Grouping فیلتر می‌کند. HAVING پس از GROUP BY برای فیلتر کردن Groupها یا نتیجه Aggregate Functionها استفاده می‌شود.

برای تبدیل امن String به Number یا Date چه کنیم؟

از TRY_CAST یا TRY_CONVERT استفاده کنید. در صورت نامعتبر بودن مقدار، خروجی NULL خواهد بود.

چگونه هزینه Query را بررسی کنیم؟

SET STATISTICS IO ON و SET STATISTICS TIME ON اطلاعات I/O و زمان را نمایش می‌دهند. Estimated یا Actual Execution Plan نیز مسیر اجرای Query را نشان می‌دهد.

جمع‌بندی

این Cheat Sheet مهم‌ترین بخش‌های T-SQL در SQL Server را در یک مسیر منظم پوشش می‌دهد: ابتدا عملیات CRUD، سپس فیلتر، Aggregation و JOIN، بعد Subquery، CTE و Window Functions، و در ادامه قابلیت‌های اختصاصی SQL Server، توابع String و Date، مدیریت Table و ابزارهای Query Tuning.

برای استفاده روزمره، لازم نیست تمام Syntaxها را حفظ کنید. مهم‌تر این است که بدانید برای هر مسئله باید سراغ کدام دسته از دستورها بروید، شرط‌ها در چه مرحله‌ای اعمال می‌شوند و چگونه نتیجه و Performance Query را بررسی کنید.

چک‌لیست نهایی SQL Server

  1. برای خواندن داده از SELECT و برای تغییر داده از دستور مناسب CRUD استفاده کرده‌اید.
  2. دستورهای UPDATE و DELETE دارای WHERE کنترل‌شده هستند.
  3. برای محدود کردن نتیجه از TOP یا OFFSET FETCH استفاده شده است، نه LIMIT.
  4. مقدارهای NULL با IS NULL یا IS NOT NULL بررسی می‌شوند.
  5. شرط Rowها در WHERE و شرط Groupها در HAVING قرار گرفته است.
  6. نوع JOIN با نیاز واقعی Result Set هماهنگ است.
  7. برای Ranking یا Running Total از Window Functions استفاده شده است.
  8. برای دریافت Identity جدید از SCOPE_IDENTITY() یا OUTPUT استفاده شده است.
  9. Dynamic SQL با sp_executesql و Parameter نوشته شده است.
  10. برای Queryهای مهم، Statistics و Execution Plan بررسی شده‌اند.

منبع تدوین مقاله

این مقاله به‌صورت مستقل و فارسی، بر اساس موضوعات و ترتیب آموزشی صفحه زیر تدوین شده است:

  • SQL Server Cheat Sheet: Every T-SQL Command You Need (2026) – AI2SQL

تاریخ درج‌شده در صفحه منبع: 12 مارس 2026. مثال‌ها برای انتشار فارسی بازنویسی و یکپارچه شده‌اند و نام دستورها و اصطلاحات SQL بدون ترجمه حفظ شده‌اند.

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

حرف 500 حداکثر