Showing posts with label T-SQL. Show all posts
Showing posts with label T-SQL. Show all posts

Friday, September 4, 2026

SQL Server: Error Handling Using TRY...CATCH and Transactions

Error handling is an important part of database programming. When an operation fails because of a foreign key violation, duplicate key, or another database error, it is useful to return a meaningful error message to the application.

The following example demonstrates how to use TRY...CATCH, transactions, ERROR_NUMBER(), and RAISERROR to handle errors in a stored procedure. The example also shows how a foreign key dependency can prevent a record from being deleted.

Create the Primary Table

Create a table named TEST1 with two fields: T_ID and T_NAME.

CREATE TABLE TEST1
(
    T_ID INT IDENTITY(1,1) PRIMARY KEY,
    T_NAME VARCHAR(25)
);
GO

Create the Dependent Table

Create another table named TEST2_DEPEND with two fields: TD_ID and TD_ADDRESS.

CREATE TABLE TEST2_DEPEND
(
    TD_ID INT FOREIGN KEY REFERENCES TEST1(T_ID),
    TD_ADDRESS VARCHAR(25)
);
GO

Insert Records into TEST1

INSERT INTO TEST1 (T_NAME) VALUES ('Rakesh'); GO INSERT INTO TEST1 (T_NAME) VALUES ('Kumar'); GO INSERT INTO TEST1 (T_NAME) VALUES ('Bardhan'); GO

Create a Stored Procedure for Insert and Delete

The following stored procedure accepts an operation type:

  • I — Insert

  • D — Delete

The procedure uses a transaction so that changes can be rolled back if an error occurs.

ERROR_NUMBER() is used to identify the error raised by SQL Server. For example, error 547 is commonly associated with a foreign key constraint violation.

CREATE PROCEDURE USP_TEST1 ( @OP_TYP VARCHAR(3), @ID INT, @ADDRESS VARCHAR(30) = NULL ) AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; IF @OP_TYP = 'I' BEGIN INSERT INTO TEST1 (T_NAME) VALUES (@ADDRESS); END ELSE IF @OP_TYP = 'D' BEGIN DELETE FROM TEST1 WHERE T_ID = @ID; END COMMIT TRANSACTION; END TRY BEGIN CATCH DECLARE @ERROR_NUMBER INT; SET @ERROR_NUMBER = ERROR_NUMBER(); IF XACT_STATE() <> 0 BEGIN ROLLBACK TRANSACTION; END IF @ERROR_NUMBER = 547 BEGIN RAISERROR( 'Cannot delete! The value has a dependency in another table.', 16, 1 ); END ELSE IF @ERROR_NUMBER = 2627 BEGIN RAISERROR( 'Cannot insert! A duplicate value already exists.', 16, 1 ); END ELSE BEGIN RAISERROR( 'An error occurred while processing the database operation.', 16, 1 ); END END CATCH END; GO

Insert a Value into the Foreign Key Table

The following statement creates a dependency on the record with T_ID = 2.

INSERT INTO TEST2_DEPEND (TD_ID, TD_ADDRESS) VALUES (2, 'Banaglore'); GO

Execute the Procedure

Now try to delete the record with T_ID = 2 from the primary table.

EXEC USP_TEST1 'D', 2;

Because TEST2_DEPEND contains a record that references TEST1.T_ID = 2, SQL Server raises a foreign key violation.

Expected Output

Cannot delete! The value has a dependency in another table.

The transaction is rolled back, so the failed delete does not change the data.

Checking SQL Server Error Messages

SQL Server provides system views that can be used to view available error messages and language information.

SELECT *
FROM sys.messages;
SELECT *
FROM sys.syslanguages;

Remarks

This example demonstrates how database errors can be handled inside a stored procedure and converted into more meaningful messages for the application.

Using transactions together with TRY...CATCH helps maintain data consistency when an operation fails. The ERROR_NUMBER() function can be used to identify the specific SQL Server error and take appropriate action.

For new development, THROW is generally preferred over RAISERROR for re-throwing or generating errors. This example uses RAISERROR because it demonstrates the approach used in the original article.


SQL Server: Adding IDENTITY Property to an Existing Column

Adding the IDENTITY property to an existing column in SQL Server is not as straightforward as changing the column data type. SQL Server does not provide a simple ALTER COLUMN statement to add the IDENTITY property to an existing column.

One way to accomplish this is to create a new IDENTITY column, remove the old column, and then rename the new column with the original column name. The following example shows the steps.

Steps to Add the IDENTITY Property

  • Add a new column with the `IDENTITY` property. 
  • Drop the constraint, if any.
  •  Drop the old column.
  • Rename the new column with the old column name.

Existing Table

CREATE TABLE Employee
(
Emp_Id INT PRIMARY KEY,
Emp_Name VARCHAR(100)
); 

1. Add a New Column with IDENTITY


ALTER TABLE Employee
ADD EmpNew_ID INT IDENTITY(1,1);

2. Drop the Primary Key Constraint

If the existing column is a primary key, first drop the primary key constraint.

ALTER TABLE Employee
DROP CONSTRAINT PK__Employee__262359AB07020F21;

Note: The constraint name above is an example. The actual constraint name may be different in your database.

3. Drop the Old Column

ALTER TABLE Employee
DROP COLUMN Emp_Id

4. Rename the New Column
 

Rename the new column with the old column name:

EXEC sp_rename 'Employee.EmpNew_ID', 'Emp_Id', 'COLUMN';

Now the table has the new `IDENTITY` column with the original column name. 

Remarks

I came across this approach through one of my co-workers. At first, I thought it would be as simple as altering the existing column, but after looking into it, I realized that adding the `IDENTITY` property to an existing column requires a different approach.

The above method works by creating a new column with the `IDENTITY` property, removing the old column, and then renaming the new column.

Before using this approach, make sure you understand the impact on existing data and dependencies. If the table contains data, dropping the old column will remove that data. Also, consider any primary keys, foreign keys, indexes, constraints, triggers, and other objects that depend on the old column.

If necessary, drop or recreate the required constraints and dependent objects as part of the change.
 

Display the Table

SELECT *
FROM Employee;



SQL Server: Rename Columns or Tables Using SP_RENAME

Renaming a table or column is a common requirement when working with SQL Server. In SQL Server, the `sp_rename` procedure can be used to rename tables and columns. This article shows how to rename a column, rename a table, and change the definition of a column using `ALTER TABLE`


Rename a Column

To rename a column in SQL Server, use `sp_rename` with the `COLUMN` object type.


EXEC sp_rename 'TABLE_NAME.COLUMN_NAME', 'NEW_COLUMN_NAME', 'COLUMN';


For example:


EXEC sp_rename 'dbo.Employee.EMP_NAME', 'EMPLOYEE_NAME', 'COLUMN';

The schema name can be included in the existing column name, which is recommended when specifying the object.
 

Change the Data Type or Size of a Column

`ALTER TABLE ... ALTER COLUMN` is used to change the definition of a column. It does **not** rename the column.

For example:


ALTER TABLE Employee
ALTER COLUMN EMP_NAME VARCHAR(100);

 Rename a Table

To rename a table, use `sp_rename`:

EXEC sp_rename 'dbo.Employee', 'New_Employee';
The existing table name should include the schema when appropriate, while the new table name should be specified without the schema.

 About sp_rename

`sp_rename` changes the name of a user-created object in the current database. It can be used to rename tables, columns, indexes, and other supported objects.

 Remarks

Changing any part of an object name can break scripts and stored procedures. Microsoft recommends not using `sp_rename` to rename stored procedures, triggers, user-defined functions, or views. Instead, drop the object and re-create it with the new name.

Renaming a table or column does not automatically update references to that object. Any dependent queries, views, triggers, stored procedures, or other objects may need to be updated manually. You can use `sys.sql_expression_dependencies` to identify dependencies before renaming an object.

To rename objects, columns, and indexes, you need `ALTER` permission on the object. To rename user-defined types, `CONTROL` permission on the type is required. Renaming a database requires membership in the `sysadmin` or `dbcreator` fixed server roles.

SQL: Fetching Records One-by-One Without Using a Cursor

Fetching Records One-by-One Without Using a Cursor

The following example shows how to process records one-by-one without using a cursor.


DECLARE @EMP_ID CHAR(11);

SET ROWCOUNT 0;

SELECT *
INTO #MYTEMP
FROM Employee;

SET ROWCOUNT 1;

SELECT @EMP_ID = EMP_ID
FROM #MYTEMP;

WHILE @@ROWCOUNT <> 0
BEGIN
SET ROWCOUNT 0;

SELECT *
FROM #MYTEMP
WHERE EMP_ID = @EMP_ID;

DELETE FROM #MYTEMP
WHERE EMP_ID = @EMP_ID;

SET ROWCOUNT 1;

-- Set one ID to @EMP_ID from #MYTEMP
SELECT @EMP_ID = EMP_ID
FROM #MYTEMP;
END;

SET ROWCOUNT 0;

Remarks

Cursors are generally avoided when they are not required because row-by-row processing can be expensive compared with set-based operations.

In the above example, a temporary table is used to process the records one-by-one without explicitly declaring a cursor.

`SET ROWCOUNT 0` allows statements to process all applicable rows, while `SET ROWCOUNT 1` limits the number of rows processed by the statement to one.

The query uses this behavior to retrieve one `EMP_ID` at a time, process that record, delete it from the temporary table, and then retrieve the next `EMP_ID`.

This approach can be useful for specific requirements where records need to be processed individually without using a cursor.
 

Note: SET ROWCOUNT should be used with caution in new development. Microsoft recommends using TOP or OFFSET/FETCH where appropriate to limit the number of rows. Microsoft also advises against using SET ROWCOUNT with DELETE, INSERT, and UPDATE in new development.



SQL Server: Make Your Database Read-Only or Read-Write


Sometimes you may need to make a SQL Server database read-only for administrative or maintenance purposes.

Before setting a database to read-only, make sure that no active operations or users require write access to the database.

Using ALTER DATABASE

To set a database to read-only:

ALTER DATABASE TestDB1 SET READ_ONLY;

Once the database is read-only, users can query the existing data, but write operations such as INSERT, UPDATE, and DELETE are not allowed.

If the database was set to read-only temporarily and you want to allow write operations again, use:

ALTER DATABASE TestDB1 SET READ_WRITE;
Using SP_DBOPTION

Older versions of SQL Server provided the sp_dboption system stored procedure for changing database options.

For example:

EXEC sp_dboption 'TestDB1', 'READ ONLY', 'TRUE';

However, sp_dboption is deprecated. For current SQL Server versions, it is recommended to use ALTER DATABASE instead.

Denying INSERT and UPDATE Permissions

 Another approach is to prevent specific users or roles from modifying particular tables rather than making the entire database read-only.

For example:

DENY INSERT, UPDATE ON dbo.TableName TO UserName;

The DENY permission takes precedence over a corresponding GRANT, so this approach can be useful when you want users to have access to the database but prevent modifications to specific tables.

Choose the approach based on your requirement:

• Use ALTER DATABASE ... SET READ_ONLY when the entire database should be read-only.

• Use DENY when only specific users or tables need to be protected from modifications.


SQL Server: Find the Number of Columns in a Table

The following function can be used to find the number of columns in a specified table. The function returns an INT value, so it is a scalar-valued function.

Create the Function

-- Function for finding the number of columns in a given table

CREATE FUNCTION FUN_COL_COUNT(@T_NAME VARCHAR(50))
RETURNS INT
AS
BEGIN
    DECLARE @CNT INT;

    SELECT @CNT = MAX(ORDINAL_POSITION)
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = @T_NAME;

    RETURN @CNT;
END

Run the Function

SELECT dbo.FUN_COL_COUNT('Table_Name');

The above statement returns the number of columns in the specified table.

Here, `dbo` represents the database schema under which the function is created.

INFORMATION_SCHEMA.COLUMNS

The INFORMATION_SCHEMA.COLUMNS view provides information about the columns in tables and views in the database. It is part of the INFORMATION_SCHEMA views provided by SQL Server and follows the SQL standard for metadata access.

The `ORDINAL_POSITION` column indicates the position of each column within the table. The function uses the maximum `ORDINAL_POSITION` value to determine the number of columns.

Note: This example uses `INFORMATION_SCHEMA.COLUMNS` for metadata access. When working specifically with SQL Server, the `sys.columns` catalog view is another commonly used option. 


SQL:Show Execution Plan of SQL Statement--SHOWPLAN_ALL

SQL Server: Displaying the Execution Plan Using SHOWPLAN_ALL

SET SHOWPLAN_ALL can be used to display the execution plan of a Transact-SQL statement without actually executing the statement.

Syntax:

SET SHOWPLAN_ALL { ON | OFF }

Example:

SET SHOWPLAN_ALL ON;

CREATE TABLE TEST_TABLE
(
    T_ID INT,
    T_NAME VARCHAR(50)
);

SET SHOWPLAN_ALL OFF;

When SET SHOWPLAN_ALL is ON, SQL Server does not execute the Transact-SQL statements. Instead, it returns detailed information about how the statements would be executed, along with estimated resource requirements.

For example, if you execute a CREATE TABLE statement while SHOWPLAN_ALL is ON, the table is not actually created. SQL Server only returns the execution-plan information for that statement.

After checking the execution plan, turn SHOWPLAN_ALL OFF:

SET SHOWPLAN_ALL OFF;

The subsequent statements will then execute normally.

Example with SELECT:

SHOWPLAN_ALL ON:

SET SHOWPLAN_ALL ON;

SELECT * FROM TEST_TABLE;

SHOWPLAN_ALL OFF:

SET SHOWPLAN_ALL OFF;

SELECT * FROM TEST_TABLE;

When SHOWPLAN_ALL is ON, SQL Server returns information for each subsequent Transact-SQL statement without executing it. The output is returned as a set of rows that represents the execution steps used by the SQL Server query processor.

The output contains information about the operators involved in executing the statement and their estimated resource requirements.

Important:

SET SHOWPLAN_ALL must be the only statement in a batch. It cannot be specified inside a stored procedure.

If you need more readable execution-plan output, SQL Server also provides:

SHOWPLAN_TEXT

SHOWPLAN_XML

SHOWPLAN_ALL

SHOWPLAN_TEXT provides a text-based execution plan, while SHOWPLAN_XML returns the execution plan in XML format.

Parallel

The execution-plan output can also contain information about whether an operator is executed in parallel.

A value of 0 means the operator is not running in parallel.

A value of 1 means the operator is running in parallel.

The Parallel value does not indicate whether the query was successfully executed. When SHOWPLAN_ALL is ON, the statement is not actually executed.

Note:

Use SHOWPLAN_ALL carefully, especially when testing statements that create, modify, or delete database objects, because those statements will not actually be executed while SHOWPLAN_ALL is ON.


Thursday, September 3, 2026

SQL Server: How to Set a Database Offline/Online

Setting a Database Offline/Online in SQL Server

There are three options to set a database offline or bring it back online.

Option 1: Using ALTER DATABASE

Set the database offline:

ALTER DATABASE TestDB1 SET OFFLINE;


Bring the database online:

ALTER DATABASE TestDB1 SET ONLINE;


Option 2: Using sp_dboption

`sp_dboption` is an older SQL Server approach for changing database options.
 

Set the database offline:

sp_dboption 'TestDB1', 'offline', true;

Bring the database online:


sp_dboption 'TestDB1', 'offline', false;


Option 3: Using SQL Server Management Studio (SSMS)

  • Open `Object Explorer`
  • Right-click the database.
  • Select `Tasks`
  • Select `Take Offline`.


The database can now be taken offline or brought back online depending on the operation you perform.

Note: Taking a database offline makes it unavailable to users until it is brought back online. The `sp_dboption` method is mainly of historical interest; for current SQL Server versions, `ALTER DATABASE` or SSMS is the preferred approach.

SQL Server: Delaying SQL Execution Using WAITFOR

WAITFOR in SQL Server
 

Example 1 – WHILE Loop


-- USE WAITFOR TO DELAY EXECUTION FOR A SPECIFIED TIME

GO

DECLARE @T INT

SET @T = 1

WAITFOR DELAY '00:00:10'

WHILE @T <= 10
BEGIN
    PRINT 'MANOJ_KUMAR'

    SET @T = @T + 1
END

GO


Example 2 – WAITFOR DELAY



GO

WAITFOR DELAY '00:00:02'

SELECT 'THIS IS DB BLOG'

GO


Description

`WAITFOR` is used in SQL Server to delay the execution of a batch, stored procedure, or transaction for a specified period of time.

The delay can be specified using `WAITFOR DELAY`, with the maximum delay being up to 24 hours.

The actual delay may be slightly longer than the specified time, depending on the activity and available resources on the SQL Server.

Every `WAITFOR` statement requires a thread while it is waiting. If too many `WAITFOR` statements are running at the same time, they can consume server resources and may contribute to thread starvation.

`WAITFOR` does not change the semantics of a query. It simply makes the execution wait for the specified period before continuing.


Conclusion

`WAITFOR` can be useful for testing scenarios where you need to introduce a delay in SQL Server. It can also be used to simulate certain blocking or timing situations during troubleshooting and testing.