In SQL Server, these four components form the execution hierarchy:
Connection → Batch → Transaction → Statement
A connection represents a physical channel between client and server, established via protocols like TCP/IP or Named Pipes. Each connection maintains:
- Security context (login credentials)
- Session settings (ANSI_NULLS, QUOTED_IDENTIFIER etc.)
- Temporary objects scope
-- C# connection example
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
// Work happens here
}
A batch is one or more T-SQL statements sent to SQL Server for execution as a single unit. Key characteristics:
- Parsed and compiled as a unit
- GO is the batch separator in SSMS
- Error handling scope (batch-aborting vs. statement-level errors)
-- Example batch
SELECT * FROM Customers WHERE Region = 'WA';
GO -- Batch separator
UPDATE Orders SET ShippedDate = GETDATE() WHERE OrderID = 10248;
Transactions provide atomicity through ACID properties. They can span batches or be contained within a single statement:
-- Explicit transaction
BEGIN TRANSACTION;
UPDATE Accounts SET Balance = Balance - 100 WHERE AccountID = 1;
UPDATE Accounts SET Balance = Balance + 100 WHERE AccountID = 2;
COMMIT TRANSACTION;
-- Single statement transaction (implicit)
UPDATE Products SET Price = Price * 1.1;
Individual SQL commands like SELECT, INSERT, etc. Each statement:
- May be auto-committed if not in explicit transaction
- Can generate its own execution plan
- May be recompiled independently within a batch
The practical relationships between these components:
1 Connection : 1..* Batches
1 Batch : 1..* Transactions
1 Transaction: 1..* Statements
1 Statement : 1..1 Transactions (at execution time)
Connection pooling: Physical connections are reused while logical connections are created/destroyed
Batch errors: A syntax error in batch prevents entire batch execution, while runtime errors may allow partial execution
-- This entire batch fails due to syntax error
SELECT * FROM NonExistentTable;
SELECT GETDATE();
GO
-- This batch executes partially
SELECT * FROM ExistingTable;
RAISERROR('Manual error', 16, 1);
SELECT GETDATE(); -- This executes if XACT_ABORT is OFF
GO
SQL Server maintains @@TRANCOUNT to track nested transactions:
BEGIN TRANSACTION; -- @@TRANCOUNT = 1
SAVE TRANSACTION SavePoint1;
BEGIN TRANSACTION; -- @@TRANCOUNT = 2
COMMIT TRANSACTION; -- @@TRANCOUNT = 1
ROLLBACK TRANSACTION SavePoint1; -- Partial rollback
COMMIT TRANSACTION; -- Final commit
When working with SQL Server, it's crucial to understand four key concepts and their interrelationships:
- Connection: A physical communication channel between client and server (TCP/IP, named pipes, etc.)
- Statement: A single T-SQL command (SELECT, INSERT, UPDATE, DELETE, etc.)
- Batch: A group of one or more statements sent to SQL Server for execution
- Transaction: A logical unit of work that follows ACID properties
A connection represents a session with the database server, established through connection pooling or explicit connection opening:
-- ADO.NET connection example
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Work with the connection here
} // Connection automatically closed when disposed
Statements are the atomic units of execution. Multiple statements can be grouped into batches:
-- Single statement
SELECT * FROM Customers WHERE CustomerID = 1;
-- Batch with multiple statements
SELECT * FROM Customers;
SELECT * FROM Orders;
GO -- Batch separator in SQL Server Management Studio
Batches have important implications for execution:
- Parsed and compiled as a unit
- Variables declared in a batch aren't visible to other batches
- GO is a client tool directive (not a T-SQL keyword)
-- Batch boundary example
DECLARE @Count INT;
SELECT @Count = COUNT(*) FROM Customers;
PRINT 'Customer count: ' + CAST(@Count AS VARCHAR);
GO -- Batch ends here
-- This would fail because @Count isn't visible
PRINT @Count;
Transactions can span multiple batches or be contained within a single batch:
-- Explicit transaction
BEGIN TRANSACTION;
UPDATE Accounts SET Balance = Balance - 100 WHERE AccountID = 1;
UPDATE Accounts SET Balance = Balance + 100 WHERE AccountID = 2;
COMMIT TRANSACTION;
-- Implicit transaction (single statement)
INSERT INTO Orders (OrderDate, CustomerID) VALUES (GETDATE(), 42);
The relationships between these concepts form a hierarchy:
- 1 Connection → 1+ Batches
- 1 Batch → 1+ Statements
- 1 Batch → 0+ Transactions (1 by default)
- 1 Transaction → 1+ Batches (when using distributed transactions)
Understanding these relationships helps with:
- Connection pooling configuration
- Transaction isolation level management
- Error handling strategies
- Performance optimization
-- Error handling in batches and transactions
BEGIN TRY
BEGIN TRANSACTION;
-- Batch 1
INSERT INTO Products (Name) VALUES ('Widget');
GO
-- Batch 2
INSERT INTO Inventory (ProductID, Quantity) VALUES (SCOPE_IDENTITY(), 100);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW;
END CATCH
The interaction between these concepts affects performance:
- Multiple small batches vs. one large batch
- Transaction duration and lock contention
- Connection pooling overhead
-- Efficient batch processing example
-- Instead of:
INSERT INTO LogTable (Message) VALUES ('Message 1');
INSERT INTO LogTable (Message) VALUES ('Message 2');
-- Use:
INSERT INTO LogTable (Message)
VALUES ('Message 1'), ('Message 2');