Click here to Skip to main content
15,882,152 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to write a store procedure to delete huge(million of records) in chunk of small size. Since there are many such tables under different schema instead of writing different store procedure for each tables.
For example:
spDeleteRecords 'dbo.tblEmployee', 1000, '00:00:05';

What I have tried:

CREATE PROCEDURE spDeleteRecord
@SchemaTableName varchar(100),
@DeleteBatchSize INT,
@DelayTime DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @DeleteRowCount INT
SET @DeleteRowCount = 1

WHILE (@DeleteRowCount > 0)
BEGIN
BEGIN TRANSACTION
DELETE TOP(@DeleteBatchSize) @SchemaTableName;
SET @DeleteRowCount = @@ROWCOUNT;
PRINT @DeleteRowCount;
COMMIT
WAITFOR DELAY @DelayTime
END
END
GO
Posted
Updated 17-May-18 11:34am

This is one case where you have no choice but to use dynamic SQL. However, you should carefully validate the argument to avoid any possibility of a SQL Injection[^] vulnerability.

Something like this should work:
SQL
CREATE PROCEDURE spDeleteRecord
(
    @SchemaTableName varchar(100),
    @DeleteBatchSize int,
    @DelayTime time
)
AS
BEGIN
DECLARE @TableID int, @SchemaName sysname, @TableName sysname;
DECLARE @Query nvarchar(max), @params nvarchar(max), @DelayTimeValue char(8);
    
    SET NOCOUNT ON;
    
    SET @TableID = OBJECT_ID(@SchemaTableName, 'U');
    If @TableID Is Null RAISERROR('Table "%s" does not exist.', 16, 1, @SchemaTableName);
    
    SET @SchemaName = QUOTENAME(OBJECT_SCHEMA_NAME(@TableID));
    SET @TableName = QUOTENAME(OBJECT_NAME(@TableID));
    
    SET @Query = N'
DECLARE @DeleteRowCount int = 1;
WHILE (@DeleteRowCount > 0)
BEGIN
    BEGIN TRANSACTION;
    DELETE TOP(@DeleteBatchSize) ' + @SchemaName + N'.' + @TableName + N';
    SET @DeleteRowCount = @@ROWCOUNT;
    PRINT @DeleteRowCount;
    COMMIT;
    
    WAITFOR DELAY @DelayTimeValue;
END';
	
    SET @params = N'@DeleteBatchSize int, @DelayTimeValue char(8)';
    SET @DelayTimeValue = Convert(char(8), @DelayTime, 108);
    
    EXEC sp_executesql @Query, @params, 
        @DeleteBatchSize = @DeleteBatchSize, 
        @DelayTimeValue = @DelayTimeValue
    ;
END
GO
 
Share this answer
 
v2
--Add where clause and debug mode
CREATE PROCEDURE spDeleteRecord
(
@SchemaTableName varchar(100),
@DeleteBatchSize int,
@DelayTime time,
@Whereclause varchar(1000) ,
@debug smallint =1
)
AS
/**************

Example: 1.exec spDeleteRecord 'dbo.test',10,'00:00:10','where logtime < dateadd(yy,-1,getdate())',1
2.exec spDeleteRecord 'dbo.test',10,'00:00:10','where logtime < dateadd(yy,-1,getdate())',0

Create Date: 05/17/2018

Modified Date:

Version :1.0
******************/
BEGIN
DECLARE @TableID int, @SchemaName sysname, @TableName sysname;
DECLARE @Query nvarchar(max), @params nvarchar(max), @DelayTimeValue char(8);

SET NOCOUNT ON;

SET @TableID = OBJECT_ID(@SchemaTableName, 'U');
If @TableID Is Null RAISERROR('Table "%s" does not exist.', 16, 1, @SchemaTableName);

SET @SchemaName = QUOTENAME(OBJECT_SCHEMA_NAME(@TableID));
SET @TableName = QUOTENAME(OBJECT_NAME(@TableID));

SET @Query = N'
DECLARE @DeleteRowCount int = 1;
WHILE (@DeleteRowCount > 0)
BEGIN
BEGIN TRANSACTION;
DELETE TOP(@DeleteBatchSize) ' + @SchemaName + N'.' + @TableName + ' ' + @WhereClause + N';
--DELETE TOP(@DeleteBatchSize) ' + @SchemaName + N'.' + @TableName + ' ' + N';
SET @DeleteRowCount = @@ROWCOUNT;
PRINT @DeleteRowCount;
COMMIT;

WAITFOR DELAY @DelayTimeValue;
END';

SET @params = N'@DeleteBatchSize int, @DelayTimeValue char(8)';
SET @DelayTimeValue = Convert(char(8), @DelayTime, 108);

IF @debug = 1
BEGIN

PRINT 'exec sp_executesql N''' + @Query + ''', N''' + @params + ''', '+ ' @DeleteBatchSize = ' + convert(varchar(30),@DeleteBatchSize) + ', '
+ ' @DelayTimeValue = ''' + @DelayTimeValue + ''''

END
ELSE
BEGIN
EXEC sp_executesql @Query, @params,
@DeleteBatchSize = @DeleteBatchSize,
@DelayTimeValue = @DelayTimeValue;
END




END
GO
 
Share this answer
 
Comments
Richard Deeming 18-May-18 10:10am    
Congratulations - you've just re-introduced the SQL Injection[^] vulnerability we were trying to avoid, and destroyed your database!

NEVER use string concatenation to build a SQL query. ALWAYS use a parameterized query.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900