截断表需要什么权限?


14

我有一个对数据库具有以下权限的SQL帐户:

在此处输入图片说明

db_executor您看到此帐户是该帐户成员的角色是通过以下脚本创建的:

CREATE ROLE [db_executor] AUTHORIZATION [dbo]
GO

GRANT EXECUTE TO [db_executor] 
GO

当我运行一个selectupdateinsertdelete放在桌子上,它工作正常。当我尝试到truncate表时,它给了我这个错误信息:

无法找到对象“ TableName”,因为该对象不存在或您没有权限。

该帐户缺少什么权限?


TRUNCATE TABLE是DDL,而不是DML。
RBarryYoung

Answers:


26

查找此信息的最佳位置是在线书籍。TRUNCATE TABLE 此处的文章指示:

所需的最低权限为table_name的ALTER。默认情况下,表所有者,sysadmin固定服务器角色的成员以及db_owner和db_ddladmin固定数据库角色的TRUNCATE TABLE权限是不可转让的。但是,您可以将TRUNCATE TABLE语句合并到模块(例如存储过程)中,并使用EXECUTE AS子句为模块授予适当的权限。

因此,ALTER是所需的最低权限。您可以以DB Owner的身份获得,也可以以DB_DDLAdmin的身份获得。或者只是授予变更。

如果您考虑截断的作用及其工作方式,这是有道理的,这是一个非常“严谨”的命令,可以清空数据表并快速进行处理。


12

根据BOL中的此参考资料

所需的最低权限为table_name的ALTER。TRUNCATE TABLE权限默认授予表所有者sysadmin固定服务器角色的成员以及db_ownerdb_ddladmin固定数据库角色,并且不可转让。但是,您可以将TRUNCATE TABLE语句合并到模块(例如存储过程)中,并使用EXECUTE AS子句为模块授予适当的权限。


3

您可以创建一个存储过程,并仅以所有者身份对一个表执行存储过程,或者对任何表进行存储过程。在下一个代码中,存储过程将截断任何表而无需征求db_owner或的许可:

USE [database name]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:      Yimy Orley Asprilla
-- Create date: Julio 16 de 2014
-- Description: Función para hacer TRUNCATE a una tabla.
-- =============================================
ALTER PROCEDURE [dbo].[spTruncate]
    @nameTable varchar(60)  


WITH EXECUTE AS OWNER
AS

    SET NOCOUNT OFF;

    DECLARE @QUERY NVARCHAR(200);

    SET @QUERY = N'TRUNCATE TABLE ' + @nameTable + ';'


    EXECUTE sp_executesql @QUERY;

这是一个好主意,但可以很好地改进。例如,添加try..catch,另一件事是检查约束,特别是外键以及身份字段,需要重新设定它们的种子。您可以在过程中拥有所有这些。如果这样做,请共享新代码。;)
Marcello Miorelli 2015年

1

您可以创建一个存储过程,并仅以所有者身份对一个表执行存储过程,或者对任何表进行存储过程。在下一个代码中,存储过程将截断任何表,而无需授予db_owner或其他权限。此版本的SP中包含错误处理和SQL注入预防

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


/****** Se validan el parametro de entrada @strTabla para evitar un SQL inyección, Yimy Asprilla ******/
CREATE PROCEDURE [dbo].[spTruncate] 
        @strTabla VARCHAR(50)
WITH EXECUTE AS OWNER
AS
-- =============================================
 -- Author:  Yimy Asprilla
 -- Create date: Julio 16 de 2014
 -- Update: September 21 2017
 -- Description: Función para hacer TRUNCATE a una tabla si ser owner de la tabla. con manejo de errores y SQL Inyection
 -- =============================================
SET NOCOUNT ON

DECLARE @strSQL VARCHAR(500);
DECLARE @object_id int;

SET @object_id = OBJECT_ID(@strTabla);

BEGIN TRY
    IF @object_id IS NOT NULL 
        BEGIN;
            BEGIN TRANSACTION;
            SET @strSQL = 'TRUNCATE TABLE [' + @strTabla + '];'
            EXECUTE (@strSQL);
            COMMIT TRANSACTION;
        END;
    ELSE
    BEGIN;
        PRINT N'La Tabla: ' + @strTabla + ' No existe';
    END;
END TRY
BEGIN CATCH  
    -- se presento un error en la ejcución y s epresenta
    PRINT N'Se presento el error: ';
    SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage;   
END CATCH;

1
这看起来与另一个答案中的代码非常相似。您和那个用户是同一用户吗?
ypercubeᵀᴹ

@ypercubeᵀᴹ-他通过添加代码防止SQL注入扩展了前面的答案。
Graeme

-1

据我了解,截断不是您可以回滚的东西。因此,开始事务/提交事务是不必要的。


这不是真的,很容易测试,请删除\更改此答案
Marcello Miorelli

BEGIN TRANSACTION RADHE SELECT @@TRANCOUNT select * from [dbo].[mytable] truncate table [dbo].[mytable] rollback select * from [dbo].[mytable] /*COMMIT TRAN RADHE*/ SELECT @@TRANCOUNT
Marcello Miorelli
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.