The postings on this site are my own and do not represent my Employer's positions, advice or strategies.

LifeAsBob - Blog

 

Home

No Ads ever, except search!
Wednesday, May 1, 2024 Login
Public

Grant Truncate Table Permissions in SQL Server ? 3/3/2008 3:24:36 PM

This has been a thorn in my side as long as I have worked with SQL Server.  There are times you want to grant truncate table permissions, either on a table or all tables etc to a specific user and/or service account, BUT you do not want to grant any alter or DDL privlidges or worse db owner!

Now why Microsoft, in SQL Server 2005 did not make this available, I do not know; as smart as the people who I have seen and met that work on the product, I'm sure they could have overcome any technical issue given them.  And please don't use ANSI Standard or some other weak excuse.  I want to be able to type "Grant Truncate on Table to User", just like Select, Update or Delete.  Too BAD for me.

Fortunately Micro$oft did give us a "fishing pole", so go learn how to fish and explore: execute as.  With this procedure you can delegate and impersonate to accomplish tasks. 

So the basic setup we devised, (which was based on a model used by our Oracle group):

  1. Stored procedure - using Execute As to elevate rights
  2. Control Table - to determine which tables a user is authorized to truncate
  3. Audit Table - who, what and when (could be enhanced for why !)

The scripts below need a slight review and may need work for you particular enviornment, but the "guts" of the process is here.  Note that the control and audit table are in a dedicated DBA Schema.

USE {database}

GO

/****** Object: Schema [dba] Script Date: 03/03/2008 13:26:31 ******/

CREATE SCHEMA [dba] AUTHORIZATION [dbo]

/****** Object: Table [dba].[TRUNCATE_AUDIT] Script Date: 03/03/2008 13:26:15 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_PADDING ON

GO

CREATE TABLE [dba].[TRUNCATE_AUDIT](

[Truncate_Audit_Id] [int] IDENTITY(1,1) NOT NULL,

[HostName] [varchar](30) NOT NULL CONSTRAINT [DF__TRUNCATE___HostN__440B1D61] DEFAULT (host_name()),

[UserName] [varchar](30) NOT NULL,

[DATETIME] [datetime] NOT NULL CONSTRAINT [DF__TRUNCATE___DATET__44FF419A] DEFAULT (getdate()),

[TABLE_NAME] [varchar](100) NOT NULL,

[TABLE_OWNER] [varchar](30) NOT NULL,

[SUCCESS] [int] NOT NULL CONSTRAINT [DF__TRUNCATE___SUCCE__45F365D3] DEFAULT ((-1)),

CONSTRAINT [PK__TRUNCATE_AUDIT__4316F928] PRIMARY KEY CLUSTERED

(

[Truncate_Audit_Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

GO

SET ANSI_PADDING OFF

/****** Object: Table [dbo].[TRUNCATE_LIST] Script Date: 03/03/2008 13:35:01 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_PADDING ON

GO

CREATE TABLE [dba].[TRUNCATE_LIST](

[List_Id] [int] IDENTITY(1,1) NOT NULL,

[List_Table_Name] [varchar](256) NOT NULL,

CONSTRAINT [PK_dba.TRUNCATE_LIST] PRIMARY KEY CLUSTERED

(

[List_Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

GO

SET ANSI_PADDING OFF

/****** Object: StoredProcedure [dbo].[TRUNCATE_TBL] Script Date: 03/03/2008 13:27:22 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

USE [{database}]

GO

/****** Object: StoredProcedure [dbo].[TRUNCATE_TBL] Script Date: 03/03/2008 13:43:10 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE Procedure [dbo].[TRUNCATE_TBL] @tbl varchar(1000),@owner varchar(30)='dbo'

WITH EXECUTE AS SELF

as

begin

Declare @username varchar(30)

Set @username = Original_login()

 

If exists (select * from dba.truncate_list

Where [List_Table_Name] = @tbl)

Begin

Declare @rc int

Declare @truncate_Audit_id int

Insert into dba.truncate_Audit (table_name,table_owner,username)

Values (@tbl,@owner,@userName)

Set @truncate_audit_id = scope_identity()

declare @dynamic_sql nvarchar(1000)

set @dynamic_sql = 'Truncate Table ' + @owner + '.' + @tbl

--Print @dynamic_sql

set @rc = -1

BEGIN TRY

exec @rc = sp_executeSQL @dynamic_SQL

END TRY

BEGIN CATCH

DECLARE @ErrorMessage NVARCHAR(4000),

@ErrorNumber INT,

@ErrorSeverity INT,

@ErrorState INT,

@ErrorLine INT,

@ErrorProcedure NVARCHAR(200);

SELECT @ErrorNumber = ERROR_NUMBER(),

@ErrorSeverity = ERROR_SEVERITY(),

@ErrorState = ERROR_STATE(),

@ErrorLine = ERROR_LINE(),

@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

SELECT @ErrorMessage =

N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +

'Message: '+ ERROR_MESSAGE();

-- Raise an error: msg_str parameter of RAISERROR will contain

-- the original error information.

RAISERROR (@ErrorMessage,@ErrorSeverity,1,

@ErrorNumber,@ErrorSeverity,@ErrorState,@ErrorProcedure,

@ErrorLine)

RETURN @RC

END CATCH

Update dba.truncate_audit

Set success = @rc

Where truncate_audit_id = @truncate_audit_id

End

ELSE

Begin

RAISERROR('Cannot find the object because it does not exist or you do not have permissions.',

16,1,1088,16,7,'[dbo].[TRUNCATE_TBL]',1)

Return -1

End

END

 

/*

Insert into dba.truncate_list values ('DW_List')

Insert into dba.truncate_list values ('Daily_Efile')

grant exec on dbo.truncate_tbl to leap_efile_dw_pull_dev

grant exec on dbo.truncate_tbl to [hrbinc\x104041]

create table dbo.bob (col1 char(10))

-- drop table bob

*/

/*

insert into bob values ('test1')

insert into bob values ('test2')

insert into bob values ('test3')

insert into bob values ('test4')

truncate table dba.truncate_list

 

*/


Blog Home