Fact-checked by Grok 2 weeks ago

Transact-SQL

Transact-SQL (T-SQL) is Microsoft's proprietary extension to the Structured Query Language (SQL), serving as the primary programming language for the SQL Server Database Engine and related products such as Azure SQL Database. It builds on standard SQL by incorporating procedural elements, including variables for storing values, conditional execution statements, parameter passing, and mechanisms for controlling program flow. This enables developers to write complex scripts, stored procedures, functions, and triggers for querying, manipulating, and managing data in relational databases. T-SQL supports core SQL categories, such as (DDL) statements for creating, altering, or dropping database structures like tables and indexes; (DML) statements for selecting, inserting, updating, and deleting ; and transaction control statements to ensure atomicity, consistency, isolation, and durability () properties in database operations. Key features include a wide range of built-in types for handling integers, characters, dates, , and more; scalar and table-valued functions for computations; and error-handling constructs like TRY-CATCH blocks to manage exceptions during execution. As the foundational language for SQL Server since its , T-SQL continues to evolve with modern enhancements, such as data types and functions for workloads, support for , and native data type handling (as of SQL Server 2025). While largely compatible with ANSI SQL standards, T-SQL includes Microsoft-specific extensions that distinguish it from other SQL dialects, making it essential for enterprise database administration, , and application development on the ecosystem.

Overview and History

Definition and Purpose

Transact-SQL (T-SQL) is Microsoft's proprietary version of the Structured Query Language (SQL). It serves as the primary query language for and related products such as SQL Database and Synapse . As an extension to standard SQL, T-SQL integrates declarative SQL commands for data querying and manipulation with elements, including variables, conditional logic, looping constructs, and error-handling mechanisms, enabling developers to write more sophisticated database scripts and programs. The primary purpose of T-SQL is to facilitate communication between applications, tools, and the SQL Server through a unified set of commands that support both simple ad-hoc queries and complex, multi-step operations. It powers key database features such as stored procedures for encapsulating reusable logic, triggers for enforcing rules automatically upon events like inserts or updates, user-defined functions for custom computations, and for executing sequences of statements as a single unit of work. This combination allows T-SQL to handle advanced data processing directly within the database environment, reducing the need for external application code and improving performance in enterprise settings. What distinguishes T-SQL from standard SQL is its support for paradigms, which extend beyond declarative queries to include flow control and , all tightly integrated with SQL Server's ecosystem for scalable and . Common use cases include automating routine database administration tasks, such as data backups or index maintenance; developing modular code components like stored procedures to standardize business operations; and embedding application logic at the database tier to ensure and in handling sensitive . By enabling these capabilities, T-SQL supports efficient database programming while maintaining with core SQL standards where applicable.

Development and Evolution

Transact-SQL originated in the late 1980s through a partnership between and Sybase to develop a management system for the operating system. In 1989, this collaboration resulted in the release of SQL Server 1.0, which utilized Transact-SQL as its , extending standard SQL with capabilities tailored for enterprise data processing. Microsoft acquired the rights to further develop and adapt the technology independently after the partnership ended in 1994, porting it to Windows platforms and establishing T-SQL as a core component of SQL Server. Key milestones in T-SQL's evolution reflect Microsoft's focus on enhancing and developer productivity. SQL Server 2000 introduced native XML support, allowing T-SQL queries to generate, query, and update XML data directly within the database. SQL Server 2005 brought significant advancements, including Common Table Expressions (CTEs) for simplifying complex queries, TRY...CATCH blocks for structured error handling, and window functions such as ROW_NUMBER() and RANK() to align with emerging ANSI SQL standards for analytical processing. Later releases expanded these capabilities: SQL Server 2016 added JSON functions like and for seamless handling of , while SQL Server 2022 introduced tables, which incorporate blockchain-inspired cryptographic verification to ensure data immutability and integrity in append-only scenarios. Under Microsoft's , T-SQL has consistently extended ANSI SQL standards while introducing features to meet practical database and application needs. This approach includes periodic alignments, such as the of window functions in SQL Server 2005 to support SQL:2003 specifications for advanced without fully diverging from SQL semantics. T-SQL's prioritizes with relational paradigms, enabling developers to leverage both standard SQL constructs and Microsoft-specific extensions like stored procedures and triggers. As of 2025, T-SQL remains integral to SQL Database, where it supports fully managed cloud deployments with automatic scaling and . Ongoing enhancements emphasize cloud-native optimizations and integration, including native data types and capabilities in SQL Server 2025 (released November 19, 2025), allowing T-SQL queries to incorporate models directly for intelligent data retrieval and analysis. These developments ensure T-SQL's relevance in hybrid and AI-driven environments, bridging on-premises SQL Server instances with services.

Core Syntax and Elements

Data Types and Declarations

Transact-SQL (T-SQL) supports a variety of built-in scalar types categorized into exact numerics, approximate numerics, date and time, character strings, character strings, binary strings, and other specialized types. These types define the storage and behavior of in columns, variables, and parameters, ensuring and efficient querying. Among exact numeric types, stores integer values ranging from -2,147,483,648 to 2,147,483,647, occupying 4 bytes of storage. The BIT type represents Boolean values as 0 (false), 1 (true), or NULL, using minimal storage (1 bit per value, packed into bytes). For precise decimal calculations, DECIMAL(p,s) (synonymous with NUMERIC) allows a precision p up to 38 digits and scale s up to the value of p, where p specifies total digits and s the number of decimal places. Character strings include VARCHAR(n) for variable-length non-Unicode data up to 8,000 characters (or VARCHAR(MAX) for up to 2^31-1 bytes). Date and time types feature DATETIME2, which provides a range from 0001-01-01 to 9999-12-31 with fractional seconds precision up to 7 digits, offering greater accuracy than the legacy DATETIME type. Other specialized types include the data type, introduced in SQL Server 2025, which stores JSON documents in a native binary format for efficient parsing, modification, and querying using built-in functions like JSON_OBJECTAGG and JSON_ARRAYAGG. Additionally, the data type, also new in SQL Server 2025, supports storage of vector embeddings for AI and machine learning applications, using single-precision (4-byte) or half-precision (2-byte) floating-point values optimized for similarity searches, exposed as JSON arrays. User-defined types extend built-in types for consistency and reusability. Alias types are created using CREATE TYPE to base a new type on an existing system type, such as a custom string: CREATE TYPE EmailAddress FROM VARCHAR(255) NOT NULL;, enforcing domain-specific rules like nullability. Table-valued types, also defined with CREATE TYPE, allow declaration of complex structures resembling tables for passing multiple rows and columns as parameters: CREATE TYPE ProductList AS TABLE (ProductID INT PRIMARY KEY, Quantity INT);. Declarations in T-SQL specify types for local variables or parameters using the statement, which supports system, user-defined, or CLR types but not deprecated types like TEXT. The syntax is DECLARE @variable_name [AS] data_type [NOT NULL] [= initial_value];, where NOT NULL prevents null assignments and requires an initial value if specified. For example, DECLARE @Counter [INT](/page/INT) NOT NULL = 0; initializes a non-null variable. These declarations are used in batches, stored procedures, or functions to hold temporary data during execution. Type conversions ensure compatibility between mismatched types in expressions or assignments. The CAST function follows ISO standards: CAST(expression AS data_type), such as CAST(123.45 AS INT) yielding 123. CONVERT, a T-SQL-specific extension, adds a style parameter for formatting: CONVERT(VARCHAR(10), GETDATE(), 101), which formats the current date as MM/DD/YYYY (e.g., '11/10/2025'). CONVERT supports additional styles for dates, numbers, and currencies, making it preferable for output formatting over CAST.

Variables and Parameters

In Transact-SQL (T-SQL), variables are temporary storage locations used to hold data during script execution, declared with a specific syntax to specify name, data type, and optional initial value. The declaration uses the DECLARE statement, followed by the variable name prefixed with @, the data type, and an equals sign for initialization if desired. For example:
sql
DECLARE @Counter INT = 0;
DECLARE @Name NVARCHAR(50) = 'Example';
This syntax supports various data types, such as INT, VARCHAR, or user-defined types, allowing variables to store scalars or even table structures in advanced cases. Assignment to variables can occur via the SET statement for simple values or the SELECT statement for results from queries, with SET being preferred for single assignments due to its clarity and performance in certain contexts. The SET syntax is SET @variable = expression;, while SELECT allows batch assignments like SELECT @var1 = col1, @var2 = col2 FROM table;. For instance:
sql
SET @Counter = @Counter + 1;
SELECT @Total = SUM(Amount) FROM Orders;
SELECT is useful when assigning from query results but should be used judiciously to avoid unexpected multiple-row behaviors, where only the last row's value is retained unless aggregated. Parameters extend variable usage in stored procedures, functions, and dynamic SQL, categorized as input, output, or table-valued. Input parameters are declared with @param datatype [= default_value], allowing optional defaults for flexibility in calls. Output parameters use the OUTPUT keyword to return values, as in CREATE PROCEDURE GetCount @ID INT, @Count INT OUTPUT AS SELECT @Count = COUNT(*) FROM Table WHERE ID = @ID;. Table-valued parameters, introduced in SQL Server 2008, enable passing structured data via user-defined table types, declared as CREATE TYPE MyTableType AS TABLE (ID INT); and used like @tvp MyTableType READONLY. These parameters promote modular code by encapsulating inputs and outputs without global state. Scoping rules confine local variables and parameters to their declaring batch, stored procedure, function, or trigger, ensuring isolation across executions. For example, a variable declared in a batch is inaccessible in subsequent batches separated by GO. System global variables, prefixed with @@ like @@ERROR (which captures the last T-SQL statement's error code) or @@ROWCOUNT (returning affected rows), provide environment-wide status but are read-only and reset per statement. Best practices emphasize declaring variables with precise data types to optimize performance and avoid implicit conversions, initializing them to prevent undefined behavior, and favoring local over global variables for thread safety in concurrent, multi-user SQL Server environments. Avoid overusing SELECT for assignments in loops due to potential overhead, and document parameter defaults clearly in procedure definitions.

Expressions and Control Flow

Operators and Expressions

Transact-SQL (T-SQL) supports a variety of operators that enable the construction of expressions for performing computations, comparisons, and manipulations within queries and statements. Expressions in T-SQL are combinations of constants, variables, columns, scalar functions, and operators, which can be simple (a single element) or complex (joined by operators). These expressions evaluate to a single value and are fundamental to clauses like SELECT, WHERE, and control-of-flow structures. Arithmetic operators in T-SQL perform mathematical operations on numeric expressions, including addition (+), subtraction (-), multiplication (*), division (/), and modulo (%). These operators apply to numeric data types and, for + and -, also to datetime types. Any arithmetic operation involving NULL yields NULL, preserving the three-valued logic of SQL where unknown values propagate unknowns. For example, NULL + 5 evaluates to NULL. Comparison operators facilitate relational tests between expressions, returning a result under (TRUE, FALSE, or ). The standard operators are (=), (<> or !=), greater than (>), less than (<), greater than or equal (>=), and less than or equal (<=). For handling NULL, dedicated operators IS NULL and IS NOT NULL are required, as standard comparisons with NULL yield (not TRUE or FALSE). This behavior aligns with ANSI SQL standards and applies when SET ANSI_NULLS ON (the default). Logical operators combine Boolean expressions to form compound conditions: AND returns TRUE only if both operands are TRUE (FALSE or UNKNOWN otherwise), OR returns TRUE if at least one operand is TRUE (FALSE only if both are FALSE), and NOT negates a Boolean value (leaving UNKNOWN unchanged). These operators adhere to three-valued logic, as shown in the truth tables below. They are commonly used in WHERE clauses to filter rows based on multiple criteria. AND Truth Table:
Operand 1Operand 2Result
TRUETRUETRUE
TRUEFALSEFALSE
TRUEUNKNOWNUNKNOWN
FALSETRUEFALSE
FALSEFALSEFALSE
FALSEUNKNOWNFALSE
UNKNOWNTRUEUNKNOWN
UNKNOWNFALSEFALSE
UNKNOWNUNKNOWNUNKNOWN
OR Truth Table:
Operand 1Operand 2Result
TRUETRUETRUE
TRUEFALSETRUE
TRUEUNKNOWNTRUE
FALSETRUETRUE
FALSEFALSEFALSE
FALSEUNKNOWNUNKNOWN
UNKNOWNTRUETRUE
UNKNOWNFALSEUNKNOWN
UNKNOWNUNKNOWNUNKNOWN
NOT Truth Table:
InputNOT Output
TRUEFALSE
FALSETRUE
UNKNOWNUNKNOWN
String operators in T-SQL handle text manipulation within expressions. The + operator concatenates character or binary strings, columns, or a combination thereof; for instance, 'Hello' + ' World' yields 'Hello World'. As of SQL Server 2025, the || operator provides an additional standard-conforming way to concatenate strings, such as 'Hello' || ' World'. The LIKE operator performs pattern matching using wildcards: % matches zero or more characters, and _ matches exactly one character (e.g., 'ABC%' LIKE 'A_C' is FALSE, but 'ABC' LIKE 'A_C' is TRUE). Starting with SQL Server 2025, regular expression functions such as REGEXP_LIKE, REGEXP_REPLACE, REGEXP_SUBSTR, and others enable advanced pattern matching beyond LIKE, supporting complex regex patterns for searching and manipulating strings. Scalar functions such as SUBSTRING integrate seamlessly into string expressions, allowing extraction and combination, like SUBSTRING('Microsoft', 1, 4) + ' SQL' resulting in 'Micro SQL'; in SQL Server 2025, the length parameter in SUBSTRING is optional and defaults to the remaining length of the expression. Operator precedence in T-SQL determines evaluation order in expressions, with levels from highest (1) to lowest (8). Unary operators like ~ (bitwise NOT) have the highest precedence, followed by multiplicative operators (*, /, %) at level 2, additive and bitwise (+, -, &, ^, |) at level 3, comparisons at level 4, NOT at level 5, AND at level 6, and OR at level 7. Operators at the same level evaluate left-to-right. Parentheses override precedence, ensuring explicit grouping; for example, SELECT 2 + 3 * 4 yields 14 (multiplication first), but SELECT (2 + 3) * 4 yields 20.

Conditional and Looping Statements

Transact-SQL provides imperative control-of-flow constructs that enable procedural programming within SQL scripts, stored procedures, and functions, allowing developers to implement decision-making and iteration logic. These mechanisms extend beyond the declarative nature of standard SQL, incorporating elements like conditional branching and loops to handle complex business rules and data processing tasks.

IF...ELSE Statements

The IF...ELSE statement in Transact-SQL evaluates a Boolean expression and executes a specified statement or block of statements if the condition returns TRUE; an optional ELSE clause executes if the condition is FALSE or NULL. The syntax is:
IF boolean_expression
    { sql_statement | statement_block }
[ ELSE
    { sql_statement | statement_block } ]
Here, boolean_expression is any valid Transact-SQL expression that evaluates to TRUE or FALSE, and statement_block uses BEGIN...END to group multiple statements for execution as a unit. For example, to check if the current day is a weekend:
IF DATENAME(weekday, GETDATE()) IN (N'Saturday', N'Sunday')
    SELECT 'Weekend';
ELSE
    SELECT 'Weekday';
This construct is commonly used in stored procedures to test for parameter conditions or object existence before proceeding. Nesting IF statements is supported, with the depth limited only by available memory, enabling hierarchical decision trees.

CASE Expressions

The CASE expression provides multi-way conditional logic, returning a value based on evaluated conditions, and can be used in statements like SET or within larger control structures to assign values dynamically. It comes in two forms: simple CASE for equality comparisons and searched CASE for arbitrary Boolean conditions. The simple CASE syntax compares an input expression against multiple WHEN values:
CASE input_expression
    WHEN when_expression THEN result_expression
    [ ...n ]
    [ ELSE else_result_expression ]
END
The searched CASE evaluates sequential Boolean conditions:
CASE
    WHEN Boolean_expression THEN result_expression
    [ ...n ]
    [ ELSE else_result_expression ]
END
Evaluation stops at the first TRUE condition, with an optional ELSE handling unmatched cases; the return type is determined by the highest-precedence data type among the result expressions. For instance, to set a variable based on a value:
SET @status = CASE @score
    WHEN 90 THEN 'A'
    WHEN 80 THEN 'B'
    ELSE 'C'
END;
CASE supports up to 10 levels of nesting and cannot directly control execution flow like IF, but it integrates seamlessly into procedural blocks for value selection.

WHILE Loops

The WHILE loop repeatedly executes a statement or block while a Boolean condition remains TRUE, providing iteration capabilities for tasks like batch processing or recursive calculations. Its syntax is:
WHILE boolean_expression
    { sql_statement | statement_block | BREAK | CONTINUE }
Inside the loop, BREAK exits the innermost WHILE entirely, transferring control to the statement following END, while CONTINUE skips the remainder of the current iteration and re-evaluates the condition. An example that doubles product prices until exceeding a threshold, using both keywords:
WHILE (SELECT MAX(ListPrice) FROM Production.Product) < 500
BEGIN
    UPDATE Production.Product
    SET ListPrice = ListPrice * 2;
    IF (SELECT MAX(ListPrice) FROM Production.Product) > 500
        BREAK;
    CONTINUE;
END
Developers must ensure the condition eventually becomes FALSE, often using counters or state variables, to prevent infinite loops that could consume resources indefinitely.

Nested Control Structures

Transact-SQL allows nesting of IF, CASE, and WHILE within one another or in combination, such as embedding IF statements inside a WHILE loop for conditional iteration or using CASE within an IF to determine branch outcomes. For example, a WHILE loop might increment a counter while an inner IF checks boundaries to avoid overflow. BREAK and CONTINUE apply only to the innermost loop in nested WHILE structures, ensuring precise control without affecting outer iterations. This nesting supports complex algorithms, like simulating recursion in procedural code. Unlike standard SQL, which focuses on declarative queries without built-in procedural flow, Transact-SQL's imperative style—derived from its integration with SQL Server's programming model—enables these blocks for , distinguishing it from ANSI SQL's set-based paradigm.

Data Manipulation

Querying with SELECT

The SELECT statement in Transact-SQL is the primary mechanism for retrieving data from tables in SQL Server databases, allowing users to specify columns, filter rows, sort results, and perform complex operations like joining multiple tables or applying functions. Its basic syntax is SELECT [ALL | DISTINCT] select_list FROM table_source [WHERE search_condition] [ORDER BY order_expression [ASC | DESC]], where the select_list defines the columns or expressions to return, table_source identifies the data source, WHERE filters rows based on conditions, and ORDER BY sorts the output. For example, to retrieve employee names sorted alphabetically, one might use SELECT FirstName, LastName FROM HumanResources.Employee ORDER BY LastName;. The DISTINCT keyword eliminates duplicate rows, as in SELECT DISTINCT Title FROM HumanResources.Employee;, ensuring unique values are returned. Joins extend the SELECT statement by combining data from multiple tables based on related columns, using the FROM clause with JOIN keywords and an ON condition. An INNER JOIN returns only matching rows from both tables, such as SELECT p.Name, sod.SalesOrderID FROM Production.Product AS p INNER JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID;, which lists products involved in sales orders. LEFT OUTER JOIN includes all rows from the left table and matching rows from the right, filling non-matches with NULL, for instance: SELECT p.Name, sod.SalesOrderID FROM Production.Product AS p LEFT OUTER JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID;. RIGHT OUTER JOIN mirrors this but prioritizes the right table, while FULL OUTER JOIN returns all rows from both with NULLs for non-matches. CROSS JOIN produces a Cartesian product without an ON clause, generating all combinations, as in SELECT e.BusinessEntityID, d.Name FROM HumanResources.Employee AS e CROSS JOIN HumanResources.Department AS d;. Aggregate functions summarize data within SELECT queries, often paired with GROUP BY to process groups of rows. Common functions include COUNT() to tally all rows, SUM(column) for totals of numeric values, AVG for averages, and MIN/MAX for extrema, all ignoring NULLs except COUNT(). For example, SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales FROM FactInternetSales GROUP BY OrderDateKey; computes daily sales totals. The GROUP BY clause divides results into groups based on specified columns, requiring non-aggregated SELECT columns to be included, while HAVING filters those groups post-aggregation, such as HAVING SUM(SalesAmount) > 10000. This contrasts with WHERE, which filters before grouping. Subqueries nest a SELECT inside another, enabling multi-step without temporary tables. Scalar subqueries return a single value for use in comparisons, like SELECT Name FROM Production.Product WHERE ListPrice > (SELECT AVG(ListPrice) FROM Production.Product);, identifying above-average priced items. Table subqueries return multiple rows, often in WHERE with IN or EXISTS, such as SELECT Name FROM Production.Product WHERE ProductSubcategoryID IN (SELECT ProductSubcategoryID FROM Production.ProductSubcategory WHERE Name = 'Wheels');. They can appear in FROM as derived tables or in SELECT lists. Correlated subqueries reference the outer query, executing per row and potentially slower, for example: SELECT DISTINCT c.LastName, c.FirstName FROM Person.Person AS c JOIN HumanResources.Employee AS e ON e.BusinessEntityID = c.BusinessEntityID WHERE 5000.00 IN (SELECT Bonus FROM Sales.SalesPerson AS sp WHERE e.BusinessEntityID = sp.BusinessEntityID);. Non-correlated subqueries run independently once. Up to 32 levels of nesting are supported. Introduced in SQL Server 2005, window functions perform calculations across row sets defined by the OVER clause, avoiding the need for self-joins or subqueries in many analytic scenarios. The OVER clause specifies PARTITION BY to divide rows into groups and ORDER BY for sequencing within partitions, as in ROW_NUMBER() OVER (PARTITION BY PostalCode ORDER BY SalesYTD DESC). Ranking functions like ROW_NUMBER() assign unique sequential numbers to rows, restarting per partition, for example: SELECT BusinessEntityID, ROW_NUMBER() OVER (ORDER BY BusinessEntityID) AS RowNumber FROM Sales.SalesPerson;, numbering salespeople sequentially. RANK() assigns ranks with gaps for ties, such as RANK() OVER (ORDER BY PostalCode), where tied postal codes share rank 1 but the next is 3. These functions apply after GROUP BY but before the final ORDER BY in query processing.

Modifying Data with INSERT, UPDATE, DELETE

Transact-SQL provides (DML) statements for modifying data in SQL Server tables, including INSERT for adding new rows, for altering existing rows, and DELETE for removing rows. These statements conform to ANSI SQL standards but include T-SQL extensions such as the OUTPUT clause for capturing affected rows and the TOP clause for limiting operations on a subset of rows, enhancing control and auditing capabilities. The INSERT statement adds one or more rows to a , using either explicit VALUES or a subquery based on SELECT to source data. The basic syntax is INSERT INTO table_name [ (column_list) ] VALUES (value_list);, where the column list is optional if all columns are specified in order, and multiple rows can be inserted in a single statement by separating value lists with commas. For example, to insert a single row into a Products table:
sql
INSERT INTO [Production](/page/Production).Product (Name, ProductNumber, SafetyStockLevel)
VALUES ('Adjustable Race', 'AR-5381', 1000);
This inserts the specified values into the corresponding columns. Alternatively, INSERT can draw from a SELECT query for bulk insertion without using BULK INSERT: INSERT INTO table_name SELECT ... FROM source_table;, which efficiently transfers rows while respecting data types and constraints. The statement modifies existing data in one or more columns of a , with the syntax UPDATE table_name SET column1 = value1, column2 = value2, ... [ FROM joined_tables ] [ WHERE condition ];. The SET clause assigns new values, which can include expressions or subqueries, and the optional WHERE filters affected rows to prevent unintended updates across the entire . T-SQL supports multi-table updates via the FROM with JOINs, allowing updates based on related data; for instance:
sql
[UPDATE](/page/Update) p
SET p.ListPrice = p.ListPrice * 1.1
FROM Production.Product p
INNER JOIN Production.ProductSubcategory s ON p.ProductSubcategoryID = s.ProductSubcategoryID
WHERE s.Name = 'Wheels';
This increases prices for products in the 'Wheels' subcategory. A key T-SQL enhancement is the , which limits the update to a specified number of rows, such as UPDATE [TOP](/page/Top) (10) table_name SET ..., applied to a random selection unless ordered by an ORDER BY . The OUTPUT can capture pre- and post-update values for auditing, like OUTPUT inserted.column, deleted.column. The DELETE statement removes rows from a , using the syntax DELETE FROM table_name [ FROM joined_tables ] [ WHERE condition ];. Without a WHERE , it deletes all rows, but typically a condition specifies targeted rows, such as DELETE FROM Production.Product WHERE DiscontinuedDate IS NOT NULL;. Similar to , T-SQL allows the FROM for joins to delete based on related tables, enabling complex criteria like DELETE FROM p FROM Production.Product p INNER JOIN Production.ProductModel m ON p.ProductModelID = m.ProductModelID WHERE m.Name LIKE 'Road%';. The limits deletions, e.g., DELETE TOP (5) FROM table_name WHERE ..., again on a random subset unless ordered. The OUTPUT clause supports capturing deleted rows, as in DELETE FROM table_name OUTPUT deleted.* INTO @audit_table;, useful for changes without additional queries. Introduced in SQL Server 2008, the MERGE statement performs upsert operations by combining INSERT, , and DELETE logic in a single statement based on a join between source and target tables. Its syntax is MERGE target_table AS TARGET USING source_table AS SOURCE ON join_condition WHEN MATCHED THEN [UPDATE](/page/Update) SET ... [ WHEN NOT MATCHED BY TARGET THEN INSERT ... ] [ WHEN NOT MATCHED BY SOURCE THEN DELETE ];, allowing conditional actions: update matched rows, insert unmatched source rows, and optionally delete unmatched target rows. For example:
sql
MERGE INTO Sales.Orders AS target
USING (SELECT OrderID, CustomerID, OrderDate FROM NewOrders) AS source
ON target.OrderID = source.OrderID
WHEN MATCHED THEN
    [UPDATE](/page/Update) SET target.ShipDate = GETDATE()
WHEN NOT MATCHED BY TARGET THEN
    INSERT (OrderID, CustomerID, OrderDate)
    VALUES (source.OrderID, source.CustomerID, source.OrderDate);
This updates shipping dates for existing orders and inserts new ones, with the TOP clause applicable to limit joined rows and OUTPUT for tracking actions. MERGE requires a unique index on the join column and cannot target views without INSTEAD OF triggers.

Bulk Data Operations

Transact-SQL provides mechanisms for efficiently loading large volumes of data into SQL Server tables, primarily through the BULK INSERT statement, which imports data directly from files such as or text formats. This operation is designed for high-performance scenarios, bypassing the overhead of individual row insertions to handle datasets comprising millions of rows in ETL () processes. Unlike standard INSERT statements, which process data row by row and are better suited for smaller, ad-hoc modifications, BULK INSERT minimizes and locking to achieve significantly faster throughput for bulk imports. The basic syntax of BULK INSERT is as follows:
BULK INSERT [database_name].[schema_name].[table_or_view_name]
FROM 'data_file_path'
WITH (
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
);
Here, the statement specifies the target and the source , with options defining the 's ; for instance, FIELDTERMINATOR delimits columns (defaulting to ), and ROWTERMINATOR separates rows (defaulting to return-line feed). Additional options enhance flexibility: FORMATFILE specifies a non-XML format to map complex data to columns, BATCHSIZE controls the number of rows committed per to manage and risks (defaulting to the entire ), and ERRORFILE directs rejected rows to a separate log for error analysis. These features support diverse formats and improve reliability during imports. For ad-hoc bulk loads without direct file access by the SQL Server service, alternatives include the OPENROWSET function with the BULK option, used in an INSERT...SELECT statement like INSERT INTO table SELECT * FROM OPENROWSET(BULK 'file_path', FORMAT = 'CSV', FIELDTERMINATOR = ',', ROWTERMINATOR = '\n') AS DataSource;, which treats the file as a rowset data source and supports table hints such as TABLOCK for locking optimization. Another method involves the bcp (bulk copy program) utility, a command-line tool for importing data, which can be invoked from T-SQL via the deprecated xp_cmdshell extended stored procedure, though this approach is discouraged due to security vulnerabilities and is disabled by default. Performance benefits of these bulk operations are pronounced for large-scale data ingestion; for example, BULK INSERT can process millions of rows in seconds by using minimal logging modes and reducing contention, making it ideal for ETL pipelines where row-by-row INSERT would be impractically slow due to per-row transaction costs. To maximize efficiency, options like TABLOCK should be applied to acquire exclusive locks early, and batch sizes tuned based on available resources. Security is a critical aspect of bulk operations, as BULK INSERT requires the executing user to hold INSERT permissions on the target table and the ADMINISTER BULK OPERATIONS server-level permission (or ADMINISTER DATABASE BULK OPERATIONS in SQL Database), replacing the legacy BULKADMIN role. Risks arise from external file access: the SQL Server service account must read the source file, potentially exposing the system to malicious data or unauthorized paths, especially with shares or Blob , where shared access signatures or managed identities are needed for . Best practices include validating file sources and restricting permissions to trusted locations.

Error Handling and Transactions

Exception Handling with TRY...CATCH

Transact-SQL's TRY...CATCH construct provides a structured mechanism for handling runtime errors, introduced in SQL Server 2005 to enhance exception management in database programming. This feature allows developers to enclose potentially error-prone code in a TRY block, with error-handling logic in the immediately following CATCH block, enabling graceful recovery or logging without terminating the entire batch. It captures all execution errors with a severity greater than 10 that do not sever the database connection, such as division by zero or constraint violations, while ignoring lower-severity warnings. Unlike ad-hoc error checking, TRY...CATCH supports detailed error introspection and propagation, making it a cornerstone for robust T-SQL applications. The basic syntax consists of a TRY block containing the statements to monitor, followed directly by a CATCH block for response actions, without intervening statements:
BEGIN TRY
    -- Statements that may generate an error
END TRY
BEGIN CATCH
    -- Error handling statements
END CATCH
Within the CATCH block, six system functions retrieve specifics about the caught error: ERROR_NUMBER() returns the unique ; ERROR_SEVERITY() the severity level (11-19 for caught errors); ERROR_STATE() the error state number for context; ERROR_PROCEDURE() the name of the or where the error occurred; ERROR_LINE() the line number of the error in the batch or procedure; and ERROR_MESSAGE() the descriptive text of the error. These functions ensure precise diagnostics, often used to construct log entries or custom responses. For instance, a representative example might divide two values and catch the result:
BEGIN TRY
    DECLARE @Result INT = 10 / 0;  -- This raises error 8134 (divide by zero)
END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH
This outputs the error number 8134 and the message "Divide by zero error encountered." When errors occur within transactions, the CATCH block can invoke XACT_STATE() to assess the transaction's viability before deciding on rollback. This function returns -1 if an active, uncommittable transaction exists (due to an error rendering it doomed); 1 if committable; or 0 if no transaction is active. Developers typically check IF XACT_STATE() = -1 and issue ROLLBACK TRANSACTION to avoid partial commits, preserving data consistency—especially useful when SET XACT_ABORT ON escalates certain errors. Errors caught by TRY...CATCH may leave transactions in a state requiring explicit rollback for integrity. TRY...CATCH blocks support nesting, where an inner block's error can be handled locally or allowed to propagate outward for broader management. To re-throw an error and propagate it—preserving original details like number, state, and message—use the THROW statement (introduced in SQL Server 2012) without parameters at the end of the CATCH block; alternatively, RAISERROR with the error functions achieves similar results but requires manual reconstruction. Best practices for logging involve capturing all error function outputs in the innermost CATCH, inserting them into an error table (e.g., via INSERT INTO ErrorLog (ErrorNumber, ErrorMessage, ...)), and then optionally re-throwing for caller awareness, minimizing silent failures and aiding troubleshooting. This construct supersedes the legacy @@ERROR global variable, which holds the last error number but resets after every successful statement, demanding immediate checks and risking oversight in complex scripts. TRY...CATCH offers centralized, reliable capture across multiple statements, reducing error-prone code and improving maintainability in T-SQL routines.

Transaction Control Statements

Transaction control statements in Transact-SQL (T-SQL) provide mechanisms to manage database , ensuring the (, , , ) properties that maintain during multi-statement operations. These statements allow developers to explicitly define transaction boundaries, handle nested operations, and perform partial rollbacks, which is essential for complex data modifications in SQL Server environments. By grouping (DML) statements into logical units, T-SQL transactions prevent partial updates in case of failures, supporting reliable application logic. The BEGIN [TRANSACTION](/page/Transaction) statement (abbreviated as BEGIN TRAN) initiates an explicit, local , marking the start of a that can be committed or rolled back. Its syntax is:
BEGIN { TRAN | [TRANSACTION](/page/Transaction) } [ transaction_name | @tran_name_variable ]
When executed, it increments the @@TRANCOUNT system function by 1, indicating an active . Transactions can be nested up to 32 levels deep, where each inner BEGIN [TRANSACTION](/page/Transaction) further increments @@TRANCOUNT, but only the outermost controls the final commitment of changes. Named transactions, specified via transaction_name, aid in tracking but do not alter the engine's behavior beyond the outermost level. For example:
BEGIN TRANSACTION OuterTran;
    -- DML statements here
    BEGIN TRANSACTION InnerTran;
        -- More DML statements
    COMMIT TRANSACTION InnerTran;  -- Decrements @@TRANCOUNT but keeps OuterTran active
COMMIT TRANSACTION OuterTran;  -- Commits all changes when @@TRANCOUNT reaches 0
This nesting supports modular code structures, such as in stored procedures, without prematurely finalizing data changes. The COMMIT TRANSACTION statement (or COMMIT TRAN) finalizes a , making all modifications permanent and releasing associated locks. Its syntax is:
COMMIT [ TRAN | TRANSACTION ] [ transaction_name | @tran_name_variable ]
It decrements @@TRANCOUNT by 1; if @@TRANCOUNT reaches 0 after the decrement, the changes are durably written to the database log. In nested scenarios, inner commits only reduce the count without committing data until the outermost completes. Transaction names are optional and primarily for developer reference, as the engine ignores them for commitment logic. An error occurs if COMMIT is issued when @@TRANCOUNT is already 0. For instance, in a three-level nested , three COMMIT statements are required to fully persist changes, with only the final one invoking . Conversely, the ROLLBACK TRANSACTION statement (or ROLLBACK TRAN) undoes all uncommitted changes since the transaction began or a specified savepoint, restoring the database to its pre-transaction state. Syntax:
ROLLBACK { TRAN | TRANSACTION } [ transaction_name | @tran_name_variable | savepoint_name | @savepoint_variable ]
Without a name or savepoint, it rolls back to the outermost transaction, setting @@TRANCOUNT to 0 and freeing resources. In nested contexts, a full rollback affects all levels, but partial rollbacks to inner points are possible via savepoints (detailed below). It releases locks acquired after the rollback point, except for any escalated or converted locks. An example demonstrates rolling back a named transaction after an insert, leaving subsequent operations intact only if outside the transaction. The SAVE TRANSACTION statement establishes a savepoint within an active transaction, enabling partial rollbacks without aborting the entire unit of work. Syntax:
SAVE { TRAN | TRANSACTION } { savepoint_name | @savepoint_variable }
Savepoint names are case-sensitive and limited to 32 characters; variables can hold them for dynamic use. Multiple savepoints with the same name are permitted, with rollbacks targeting the most recent instance. This feature does not decrement @@TRANCOUNT and is unavailable in distributed transactions. A common pattern in stored procedures involves setting a savepoint before risky operations and rolling back to it on failure, preserving the outer transaction. For example:
BEGIN [TRANSACTION](/page/Transaction);
    [SAVE](/page/Save) [TRANSACTION](/page/Transaction) SavePoint1;
    -- Operations that might fail
    IF @@[ERROR](/page/Error) <> 0
        [ROLLBACK](/page/Rollback) [TRANSACTION](/page/Transaction) SavePoint1;  -- Undoes only post-savepoint changes
COMMIT [TRANSACTION](/page/Transaction);
This allows fine-grained control, enhancing error recovery within transactions. T-SQL also supports implicit transactions via the SET IMPLICIT_TRANSACTIONS , which alters to automatically start transactions for certain statements when none is active. Syntax:
SET IMPLICIT_TRANSACTIONS { ON | OFF }
When set to ON, DML statements like INSERT, UPDATE, DELETE, MERGE, and others (but not simple SELECT queries without tables) begin a transaction if @@TRANCOUNT is 0, requiring an explicit COMMIT or ROLLBACK to end it. This mode aligns with ANSI standards but defaults to OFF for most connections, where each statement autocommits independently. With ON, subsequent statements within the implicit transaction increment @@TRANCOUNT only if an explicit BEGIN TRANSACTION is used. For example, enabling it before inserts ensures changes are not committed until a COMMIT is issued, preventing unintended partial updates. This setting applies at the session level and resets on connection close.

Advanced Features

Stored Procedures and Functions

Stored procedures in Transact-SQL are precompiled collections of one or more Transact-SQL statements stored under a name and processed as a single unit, allowing for modular code execution in SQL Server. They accept input parameters, return multiple values in the form of result sets, and can include control-of-flow language, making them suitable for complex operations like and implementation. Stored procedures enhance performance by caching execution plans, reduce network traffic through batching, and improve by limiting direct access. There are several types of stored procedures in . User-defined stored procedures are created by database developers using Transact-SQL or (CLR) integration and reside in user databases. System stored procedures, prefixed with sp_, are predefined in the Resource database for administrative tasks such as database maintenance and configuration queries. Extended stored procedures, prefixed with xp_, interface with external operating system components via dynamic-link libraries (DLLs) but are deprecated in favor of CLR procedures due to security risks. Temporary stored procedures, marked with # for local or ## for global scope, are stored in tempdb and automatically removed at session end or explicitly. To create a user-defined , the CREATE [PROCEDURE](/page/Procedure) statement is used, specifying the procedure name, optional with data types, and the body enclosed in BEGIN...END. For example:
sql
CREATE [PROCEDURE](/page/Procedure) GetEmployeeDetails
    @EmployeeID [int](/page/INT)
AS
BEGIN
    SELECT * FROM Employees WHERE EmployeeID = @EmployeeID;
END;
Stored procedures are executed using the EXEC or EXECUTE statement, optionally passing parameter values. For instance, EXEC GetEmployeeDetails @EmployeeID = 5; invokes the procedure and returns the result set. can be , or , enabling data passing without dynamic SQL construction, which helps mitigate risks. User-defined functions (UDFs) in Transact-SQL are routines that accept parameters, perform computations, and return a value or table, promoting code reusability within queries. Unlike ad-hoc code, UDFs cache execution plans similar to stored procedures, reducing compilation overhead. They are invoked directly in SELECT statements, WHERE clauses, or other query contexts, enhancing composability. UDFs are categorized into scalar and table-valued types. Scalar UDFs return a single value of any except text, ntext, , cursor, or , and can be inline (single ) or multi-statement. Table-valued UDFs return a ; inline versions use a single SELECT statement for the return, while multi-statement versions define a and populate it with multiple statements. Creation of a UDF employs the CREATE FUNCTION statement, including the function name, parameters, return type, and body. An example of a scalar UDF is:
sql
CREATE FUNCTION CalculateBonus (@Salary [decimal](/page/Decimal)(10,2))
RETURNS [decimal](/page/Decimal)(10,2)
AS
BEGIN
    RETURN @Salary * 0.10;
END;
Scalar UDFs are called like built-in functions, e.g., SELECT dbo.CalculateBonus(50000);, while table-valued UDFs are used in the FROM clause, such as SELECT * FROM dbo.GetEmployeeProjects(@EmployeeID);. UDFs support up to 1,024 input parameters but no output parameters. Stored procedures and user-defined functions differ in scope and capabilities. Procedures can return multiple result sets, use transactions to modify database state, and support output parameters, but they cannot be composed within queries. In contrast, functions are designed for read-only operations without side effects, must be deterministic when schema-bound, and are seamlessly integrable into SELECT statements for expressions or joins. Functions cannot execute stored procedures or use non-deterministic elements like GETDATE() unless marked appropriately, ensuring query optimization compatibility. Security features enhance both constructs. For stored procedures, the EXECUTE AS clause allows impersonation of a specified or SELF during execution, enabling controlled without granting broad permissions. Procedures can also be encrypted to hide . For functions, SCHEMABINDING binds the function to the schema of referenced objects, preventing schema changes that could invalidate it and requiring REFERENCES permission on those objects. This promotes in indexed views or computed columns.

Cursors, Triggers, and Dynamic SQL

Transact-SQL provides mechanisms for handling row-by-row operations, automated responses to data changes, and the execution of SQL statements constructed at runtime, enabling more flexible database programming. Cursors facilitate sequential processing of query results, triggers automate actions in response to data modification events, and dynamic SQL allows for the generation and execution of queries based on variables or conditions. These features, while powerful, require careful use to maintain and in SQL Server environments. Cursors in Transact-SQL enable the processing of result sets one row at a time, which is useful when set-based operations are insufficient for complex logic. A cursor is declared using the DECLARE CURSOR statement, specifying a SELECT query to define the result set, such as DECLARE employee_cursor CURSOR FOR SELECT EmployeeID, LastName FROM HumanResources.Employee;. The cursor is then opened with OPEN cursor_name, allowing rows to be fetched sequentially using FETCH NEXT FROM cursor_name INTO @variable, often within a loop that checks @@FETCH_STATUS = 0 to continue until no more rows are available. After processing, the cursor is closed with CLOSE cursor_name and deallocated with DEALLOCATE cursor_name to release resources. Cursors can be read-only or updatable, with options like FOR UPDATE OF column_list for modifications, but they are typically implemented within stored procedures for encapsulation. Triggers are special stored procedures that automatically execute in response to (DML) events on s or s, enforcing business rules or maintaining without explicit calls. They are created using CREATE TRIGGER trigger_name ON table_name AFTER {INSERT, [UPDATE](/page/Update), DELETE} AS BEGIN ... END;, where the trigger body contains Transact-SQL statements to respond to the event. For instance, an AFTER INSERT trigger might log new records to an audit . Special temporary tables, inserted and deleted, provide access to the affected rows: inserted holds new values for INSERT and [UPDATE](/page/Update) operations, while deleted holds old values for [UPDATE](/page/Update) and DELETE. INSTEAD OF triggers, which replace the triggering , are particularly useful for s to simulate updatable behavior, though only one can exist per on a or . Triggers fire once per qualifying statement, regardless of the number of rows affected, which simplifies logic but can impact on operations. Dynamic SQL in Transact-SQL allows the construction and execution of SQL statements at , accommodating scenarios where query depends on user input or variables. The recommended approach uses the system sp_executesql, invoked as EXEC sp_executesql @stmt = N'SELECT * FROM table WHERE id = @id', N'@id [INT](/page/INT)', @id = @parameter_value;, where @stmt is the Unicode string of the dynamic query, the second parameter defines parameter types, and subsequent arguments supply values. This parameterization reuses execution plans across calls, enhancing performance, and mitigates risks by separating code from data, unlike direct string concatenation with EXEC (@sql). Output parameters can be specified with OUTPUT to capture results, such as row counts or computed values. Dynamic SQL is often embedded in to build queries conditionally, but it introduces overhead from plan compilation if not parameterized properly. Best practices for these features emphasize and . Cursors should be avoided in favor of set-based operations whenever possible, as they process data sequentially and incur higher resource costs; use them sparingly for tasks like complex hierarchical updates. For triggers, employ INSTEAD OF variants on views for custom logic, set NOCOUNT ON to suppress row count messages, and test for risks with sys.triggers. In dynamic SQL, always parameterize with sp_executesql to prevent injection and leverage plan caching; fully qualify object names to avoid resolution issues. Limitations include cursors' inability to parallelize effectively, making them unsuitable for large datasets, and triggers' per-statement firing, which may lead to unexpected behavior in multi-row operations without explicit row checks via @@ROWCOUNT. These elements can be integrated into stored procedures for modular code, but their use demands balancing flexibility against SQL Server's optimization strengths.

References

  1. [1]
    Transact-SQL Reference (Database Engine) - Microsoft Learn
    Oct 28, 2025 · This article gives the basics about how to find and use the Microsoft Transact-SQL (T-SQL) reference articles.Select · Transact-SQL statements · Write Transact-SQL Statements
  2. [2]
    Get started with Transact-SQL programming - Training
    Transact-SQL (T-SQL) is a programming language for storing values, conditional execution, passing parameters, and controlling program flow. You'll learn to ...Missing: key | Show results with:key
  3. [3]
    Query and modify data with Transact-SQL - Training - Microsoft Learn
    Learn how to use Transact-SQL (T-SQL) to interact with relational databases by querying and modifying data. This course covers essential operations such as ...Introduction to Transact-SQL · Write Subqueries in T-SQL · Modify data with T-SQL
  4. [4]
    Transact-SQL statements - SQL Server - Microsoft Learn
    Nov 22, 2024 · Data Definition Language (DDL) statements defines data structures. Use these statements to create, alter, or drop data structures in a database.
  5. [5]
    Transactions (Transact-SQL) - SQL Server - Microsoft Learn
    A transaction is a single unit of work. If a transaction is successful, all of the data modifications made during the transaction are committed.
  6. [6]
    Data types (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 6, 2024 · This article provides a summary of the different data types available in the SQL Server Database Engine.Char and varchar (Transact... · Nchar and nvarchar (Transact... · Float and real · Bit
  7. [7]
    What's New in SQL Server 2022 - Microsoft Learn
    Sep 8, 2025 · Learn about new features for SQL Server 2022 (16.x), which gives you choices of development languages, data types, environments, ...
  8. [8]
    T-SQL Differences Between SQL Server and Azure SQL Database
    Jun 16, 2025 · This article discusses the Transact-SQL (T-SQL) differences between an Azure SQL Database and SQL Server.
  9. [9]
    [MS-TSQLISO02]: Glossary | Microsoft Learn
    This document uses the following terms: Transact-SQL: The Microsoft proprietary version of SQL, the structured query language. MAY, SHOULD, MUST, SHOULD NOT, ...
  10. [10]
    New Video: The History of SQL Server - Microsoft
    Feb 15, 2012 · The history of SQL Server dates back to 1989 when the product came about as a result of a partnership between Microsoft, Sybase, and Ashton-Tate.
  11. [11]
    SQL Server 2000: New Features Provide Unmatched Ease of Use ...
    Oct 24, 2019 · The article then concentrates on XML support, covering XML data retrieval and manipulation, queries, and HTTP access. It concludes with a ...<|control11|><|separator|>
  12. [12]
    WITH common_table_expression (Transact-SQL) - Microsoft Learn
    Jun 25, 2025 · A common table expression (CTE) is a temporary named result set derived from a simple query, defined within a single SELECT, INSERT, UPDATE, ...
  13. [13]
    TRY...CATCH (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · A TRY...CATCH construct catches all execution errors that have a severity higher than 10 that don't close the database connection.Missing: 2005 enhancements window
  14. [14]
    Work with JSON Data in SQL Server - Microsoft Learn
    Jul 23, 2025 · JSON support in SQL Server and Azure SQL Database lets you combine relational and NoSQL concepts. You can easily transform relational to semi- ...
  15. [15]
    Database ledger - SQL Server | Microsoft Learn
    Sep 4, 2024 · It logically uses a blockchain and Merkle tree data structures. Any operations that update a ledger table need to perform some additional tasks ...
  16. [16]
    Intelligent Applications and AI - Azure SQL Database | Microsoft Learn
    This article provides an overview of using artificial intelligence (AI) options, such as OpenAI and vectors, to build intelligent applications with Azure SQL ...Overview · Key concepts for implementing...
  17. [17]
    What's new in SQL Server 2025 Preview - Microsoft Learn
    Oct 6, 2025 · The following sections identify features that are improved or introduced in SQL Server 2025 (17.x) Preview. AI; Developer; Analytics ...SQL Tools Overview · Microsoft Logo · Release notes · Vector Data Type
  18. [18]
    Announcing SQL Server 2025 (preview): The AI-ready enterprise ...
    May 19, 2025 · SQL Server 2025, now in public preview, empowers customers to develop modern AI applications securely using their data.Your Data, Any Model... · Cloud Agility Through Azure · Get Started With Sql Server...
  19. [19]
    int, bigint, smallint, and tinyint (Transact-SQL) - Microsoft Learn
    Aug 21, 2025 · Transact-SQL reference for int, bigint, smallint, and tinyint data types. These data types are used to represent integer data.Remarks · Convert integer data
  20. [20]
    decimal and numeric (Transact-SQL) - SQL Server - Microsoft Learn
    Mar 31, 2025 · decimal and numeric are numeric data types that have a fixed precision and scale. decimal and numeric are synonyms and can be used interchangeably.
  21. [21]
    char and varchar (Transact-SQL) - SQL Server | Microsoft Learn
    Character data types that are either fixed-size, char, or variable-size, varchar. Starting with SQL Server 2019 (15.x), when a UTF-8 enabled collation is used, ...
  22. [22]
    CREATE TYPE (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Defines the data type in a column for a user-defined table type. For more information about data types, see Data Types (Transact-SQL). For more ...
  23. [23]
    DECLARE @local_variable (Transact-SQL) - SQL Server
    ### Syntax for DECLARE in T-SQL for Local Variables
  24. [24]
  25. [25]
    Expressions (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Simple expressions can be a single constant, variable, column, or scalar function. Operators can be used to join two or more simple expressions ...Syntax · Arguments
  26. [26]
    Operators (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · An operator is a symbol specifying an action that is performed on one or more expressions. The following table lists the operator categories ...Comparison Operators · Logical Operators · Bitwise operators · Arithmetic operators
  27. [27]
    Arithmetic Operators (Transact-SQL) - SQL Server - Microsoft Learn
    Dec 17, 2024 · Arithmetic operators run mathematical operations on two expressions of one or more data types. They're run from the numeric data type category.
  28. [28]
    Comparison Operators (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Comparison operators test whether two expressions are the same. Comparison operators can be used on all expressions except expressions of the text, ntext, or ...
  29. [29]
    AND (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Combines two Boolean expressions and returns TRUE when both expressions are TRUE. When more than one logical operator is used in a statement, the AND operators ...
  30. [30]
    OR (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Combines two conditions. When more than one logical operator is used in a statement, OR operators are evaluated after AND operators.<|control11|><|separator|>
  31. [31]
    NOT (Transact-SQL) - SQL Server
    ### Summary of NOT Operator in T-SQL
  32. [32]
    String operators (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · String concatenation operators can combine two or more of the following data types into one expression: character or binary strings; columns ...
  33. [33]
  34. [34]
    Operator Precedence (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · When two operators in an expression have the same precedence level, they're evaluated left to right based on their position in the expression.
  35. [35]
    Control-of-Flow - SQL Server - Microsoft Learn
    Feb 28, 2023 · The Transact-SQL control-of-flow language keywords are: BEGIN...END · RETURN · BREAK · THROW · CONTINUE · TRY...CATCH · GOTO label. WAITFOR · IF ...
  36. [36]
    IF...ELSE (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · The Transact-SQL statement that follows an IF keyword and its condition is executed if the condition is satisfied: the Boolean expression returns TRUE.ELSE (IF...ELSE) · BEGIN...END (Transact-SQL) · For Case
  37. [37]
    CASE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 18, 2025 · CASE can be used in any statement or clause that allows a valid expression. For example, you can use CASE in statements such as SELECT, UPDATE, DELETE and SET.Missing: short- | Show results with:short-
  38. [38]
    WHILE (Transact-SQL) - SQL Server - Microsoft Learn
    Jul 15, 2025 · The execution of statements in the WHILE loop can be controlled from inside the loop with the BREAK and CONTINUE keywords.Missing: CASE | Show results with:CASE
  39. [39]
    SELECT (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Retrieves rows from the database and enables the selection of one or many rows or columns from one or many tables in the SQL Server Database Engine.
  40. [40]
    SELECT examples (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · This article provides examples of using the SELECT statement. The code samples in this article use the AdventureWorks2022 or AdventureWorksDW2022 sample ...
  41. [41]
    FROM clause plus JOIN, APPLY, PIVOT (Transact-SQL)
    The FROM clause supports the SQL-92 syntax for joined tables and derived tables. SQL-92 syntax provides the INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER, and ...
  42. [42]
    Aggregate Functions (Transact-SQL) - SQL Server - Microsoft Learn
    May 23, 2023 · An aggregate function performs a calculation on a set of values, and returns a single value. Except for COUNT(*), aggregate functions ignore null values.
  43. [43]
    SELECT - GROUP BY- Transact-SQL - Microsoft Learn
    Nov 22, 2024 · SELECT list: Vector aggregates. If aggregate functions are included in the SELECT list, GROUP BY calculates a summary value for each group.Syntax · Arguments
  44. [44]
  45. [45]
    Subqueries (SQL Server) - Microsoft Learn
    Aug 21, 2025 · A subquery is a query that is nested inside a SELECT, INSERT, UPDATE, or DELETE statement, or inside another subquery.
  46. [46]
    OVER Clause (Transact-SQL) - SQL Server | Microsoft Learn
    Nov 22, 2024 · The OVER clause determines the partitioning and ordering of a rowset before the associated window function is applied.Missing: circuit | Show results with:circuit
  47. [47]
    Ranking Functions (Transact-SQL) - SQL Server
    ### Summary of Ranking Functions in T-SQL
  48. [48]
    OUTPUT clause (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Returns information from, or expressions based on, each row affected by an INSERT, UPDATE, DELETE, or MERGE statement.
  49. [49]
    TOP (Transact-SQL) - SQL Server - Microsoft Learn
    Dec 30, 2024 · When specified in the MERGE statement, the TOP clause applies after the entire source table and the entire target table are joined. And, the ...<|separator|>
  50. [50]
    INSERT (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · You can use INSERT INTO <target_table> SELECT <columns> FROM <source_table> to efficiently transfer a large number of rows from one table, such ...Syntax · Arguments
  51. [51]
    UPDATE (Transact-SQL) - SQL Server - Microsoft Learn
    Jan 29, 2025 · You can use the UPDATE statement to update a FILESTREAM field to a null value, empty value, or a relatively small amount of inline data. However ...
  52. [52]
    DELETE (Transact-SQL) - SQL Server - Microsoft Learn
    Jan 29, 2025 · This query shows the basic syntax for using a query join hint with the DELETE statement. For more information on join hints and how to use the ...Syntax · Arguments
  53. [53]
    MERGE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 8, 2025 · The MERGE statement runs insert, update, or delete operations on a target table from the results of a join with a source table.
  54. [54]
    Bulk Import and Export of Data (SQL Server) - Microsoft Learn
    Nov 22, 2024 · Methods for bulk importing and exporting data ; BULK INSERT statement, A Transact-SQL statement that imports data directly from a data file into ...
  55. [55]
    BULK INSERT (Transact-SQL) - SQL Server - Microsoft Learn
    BULK INSERT can import data from a disk or Azure Blob Storage (including network, floppy disk, hard disk, and so on).
  56. [56]
    Use a Format File to Bulk Import Data - SQL Server - Microsoft Learn
    Jun 18, 2025 · This article illustrates the use of a format file in bulk-import operations. A format file maps the fields of the data file to the columns of the table.
  57. [57]
    Use BULK INSERT or OPENROWSET (BULK...) to Import Data to ...
    Find out how to use Transact-SQL statements to bulk import data from a file to a SQL Server or Azure SQL Database table, including security considerations.
  58. [58]
    Bulk Copy with bcp Utility - SQL Server - Microsoft Learn
    The bcp utility bulk copies data between SQL Server and a data file, importing large numbers of rows or exporting data.
  59. [59]
    xp_cmdshell (Transact-SQL) - SQL Server - Microsoft Learn
    Jun 23, 2025 · Spawns a Windows command shell and passes in a string for execution. Any output is returned as rows of text.
  60. [60]
    SQL Server 2005 XML Support, Exception Handling, and More
    SQL Server 2005 still supports the @@ERROR function but it also includes the widely known TRY/CATCH paradigm. The TRY/CATCH construct is similar to the C# try/ ...Missing: enhancements CTE
  61. [61]
    ERROR_NUMBER (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 3, 2024 · This function returns the error number of the error that caused the CATCH block of a TRY...CATCH construct to execute. Transact-SQL syntax ...
  62. [62]
    ERROR_STATE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 3, 2024 · Returns the state number of the error that caused the CATCH block of a TRY...CATCH construct to be run. Transact-SQL syntax conventions. Syntax.
  63. [63]
    ERROR_PROCEDURE (Transact-SQL) - SQL Server - Microsoft Learn
    Jun 6, 2025 · When called in a CATCH block, ERROR_PROCEDURE returns the name of the stored procedure or trigger in which the error originated.
  64. [64]
    ERROR_LINE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 3, 2024 · This function returns the line number of occurrence of an error that caused the CATCH block of a TRY...CATCH construct to execute.
  65. [65]
    ERROR_MESSAGE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 3, 2024 · This function returns the message text of the error that caused the CATCH block of a TRY...CATCH construct to execute.
  66. [66]
    XACT_STATE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 4, 2024 · XACT_STATE indicates whether the request has an active user transaction, and whether the transaction is capable of being committed.Syntax · Return Type
  67. [67]
    THROW (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · If a TRY...CATCH construct isn't available, the statement batch is terminated. The line number and procedure where the exception is raised are ...
  68. [68]
    RAISERROR (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 25, 2024 · When RAISERROR is run with a severity of 11 or higher in a TRY block, it transfers control to the associated CATCH block. The error is returned ...
  69. [69]
    @@ERROR (Transact-SQL) - SQL Server | Microsoft Learn
    Sep 3, 2024 · Use the TRY...CATCH construct to handle errors. The TRY...CATCH construct also supports additional system functions (ERROR_LINE, ERROR_MESSAGE, ...
  70. [70]
    BEGIN TRANSACTION (Transact-SQL) - SQL Server - Microsoft Learn
    Explicit transactions start with the BEGIN TRANSACTION statement and end with the COMMIT or ROLLBACK statement. Transact-SQL syntax conventions. Syntax. Syntax ...
  71. [71]
    COMMIT TRANSACTION (Transact-SQL) - SQL Server
    The following example creates a table, generates three levels of nested transactions, and then commits the nested transaction. Although each COMMIT TRANSACTION ...
  72. [72]
    ROLLBACK TRANSACTION (Transact-SQL) - SQL Server
    Oct 27, 2025 · RAISERROR is the preferred statement for indicating errors. Remarks. ROLLBACK TRANSACTION without a savepoint_name or transaction_name rolls ...Arguments · Remarks · InteroperabilityMissing: CATCH | Show results with:CATCH<|control11|><|separator|>
  73. [73]
    SAVE TRANSACTION (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · A user can set a savepoint, or marker, within a transaction. The savepoint defines a location to which a transaction can return if part of the transaction is ...
  74. [74]
    SET IMPLICIT_TRANSACTIONS (Transact-SQL) - Microsoft Learn
    Sep 3, 2024 · `SET IMPLICIT_TRANSACTIONS` sets the connection to implicit mode. When ON, statements like INSERT start transactions; when OFF, it's autocommit.Syntax · Remarks
  75. [75]
    Stored procedures (Database Engine) - SQL Server - Microsoft Learn
    Nov 22, 2024 · A stored procedure in SQL Server is a group of one or more Transact-SQL statements, or a reference to a Microsoft .NET Framework common runtime language (CLR) ...Benefits of using stored... · Types of stored procedures
  76. [76]
    CREATE PROCEDURE (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 29, 2025 · CREATE PROCEDURE creates a Transact-SQL or common language runtime (CLR) stored procedure.
  77. [77]
    System Stored Procedures (Transact-SQL) - Microsoft Learn
    Jun 23, 2025 · In SQL Server, many administrative and informational activities can be performed by using system stored procedures.
  78. [78]
  79. [79]
    User-Defined Functions - SQL Server - Microsoft Learn
    Jul 18, 2025 · Transact-SQL functions are better suited for data-access intensive logic. Reduce network traffic. An operation that filters data based on some ...
  80. [80]
    CREATE FUNCTION (Transact-SQL) - SQL Server - Microsoft Learn
    Jun 23, 2025 · A user-defined function accepts parameters, performs an action such as a complex calculation, and returns the result of that action as a value.<|control11|><|separator|>
  81. [81]
    Execute user-defined functions - SQL Server - Microsoft Learn
    Apr 26, 2024 · Execute a user defined function using Transact-SQL. Scalar functions must be invoked by using at least the two-part name of the function.
  82. [82]
  83. [83]
    Create User-Defined Functions (Database Engine) - SQL Server
    Jul 18, 2025 · This article describes how to create a user-defined function (UDF) in SQL Server by using Transact-SQL.Limitations · Table-Valued Function... · Multi-Statement Table-Valued...Missing: propagation THROW
  84. [84]
    Cursors (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Opening a cursor on a result set allows processing the result set one row at a time. You can assign a cursor to a variable or parameter with a cursor data type.
  85. [85]
    CREATE TRIGGER (Transact-SQL) - SQL Server - Microsoft Learn
    Sep 29, 2025 · The Transact-SQL statements in a trigger frequently include control-of-flow language. DML triggers use the deleted and inserted logical ( ...Missing: ELSE | Show results with:ELSE
  86. [86]
    sp_executesql (Transact-SQL) - SQL Server - Microsoft Learn
    Jun 23, 2025 · sp_executesql executes a Transact-SQL statement or batch that can be reused many times, or one that is built dynamically.Syntax · Arguments
  87. [87]
    DECLARE CURSOR (Transact-SQL) - SQL Server - Microsoft Learn
    Nov 22, 2024 · Defines the attributes of a Transact-SQL server cursor, such as its scrolling behavior and the query used to build the result set on which the cursor operates.Syntax · Arguments
  88. [88]
  89. [89]
  90. [90]
  91. [91]
    SQL Injection - SQL Server - Microsoft Learn
    Jun 30, 2025 · Learn how SQL injection attacks work. Mitigate such attacks by validating input and reviewing code for SQL injection in SQL Server.