¿Qué permisos son necesarios para truncar una tabla?

14

Tengo una cuenta SQL con los siguientes permisos en una base de datos:

ingrese la descripción de la imagen aquí

El db_executorrol del que ves que esta cuenta es miembro fue creado por este script:

CREATE ROLE [db_executor] AUTHORIZATION [dbo]
GO

GRANT EXECUTE TO [db_executor] 
GO

Cuando ejecuto una select, update, inserto deleteen la mesa, que funciona bien. Cuando intento ir a truncatela mesa, me da este mensaje de error:

No se puede encontrar el objeto "TableName" porque no existe o no tiene permisos.

¿Qué permiso le falta a esta cuenta?

Mansfield
fuente
TRUNCATE TABLEes DDL, no DML.
RBarryYoung

Respuestas:

26

El mejor lugar para buscar esta información es en los libros en línea. El artículo TRUNCATE TABLE aquí indica:

El permiso mínimo requerido es ALTER en table_name. Los permisos TRUNCATE TABLE son predeterminados para el propietario de la tabla, los miembros de la función fija de servidor sysadmin y las funciones fijas de base de datos db_owner y db_ddladmin, y no son transferibles. Sin embargo, puede incorporar la instrucción TRUNCATE TABLE dentro de un módulo, como un procedimiento almacenado, y otorgar los permisos apropiados al módulo utilizando la cláusula EXECUTE AS.

Entonces ALTER es los permisos mínimos requeridos. Puede obtener eso como DB Owner, puede obtener eso como DB_DDLAdmin. O simplemente conceder alter.

Si piensa en lo que hace truncar y cómo funciona, esto tiene sentido, es un comando bastante "severo" y vacía la tabla de datos y lo hace rápidamente.

Mike Walsh
fuente
12

Según esta referencia en BOL :

El permiso mínimo requerido es ALTER en table_name . Los permisos TRUNCATE TABLE son predeterminados para el propietario de la tabla , los miembros de la función fija de servidor sysadmin y las funciones fijas de base de datos db_owner y db_ddladmin , y no son transferibles. Sin embargo, puede incorporar la instrucción TRUNCATE TABLE dentro de un módulo, como un procedimiento almacenado, y otorgar los permisos apropiados al módulo utilizando la cláusula EXECUTE AS.

Thomas Stringer
fuente
3

Puede crear un procedimiento almacenado con ejecutar como propietario para una sola tabla o un procedimiento almacenado para cualquier tabla. En el siguiente código se almacena el procedimiento para truncar cualquier tabla sin dar permiso db_owneru otro:

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;
usuario3854427
fuente
Es una buena idea, pero podría mejorarse. por ejemplo, agregando try..catch, otra cosa es verificar las restricciones, especialmente las claves foráneas, también los campos de identidad, necesitan reinicializarse. Puede tener todo eso en su procedimiento. si lo haces, comparte el nuevo código. ;)
Marcello Miorelli
0

Puede crear un procedimiento almacenado con ejecutar como propietario para una sola tabla o un procedimiento almacenado para cualquier tabla. En el siguiente código se almacena el procedimiento para truncar cualquier tabla sin dar permiso a db_owner u otro. En esta versión de SP se incluye el manejo de errores y la prevención de inyección 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;
Yimy
fuente
1
Esto se ve muy similar al código en otra respuesta. ¿Eres el mismo usuario que ese?
ypercubeᵀᴹ
-1

Por lo que yo entiendo, Truncar no es algo que pueda revertir. Por lo tanto, la transacción de inicio / transacción de confirmación es innecesaria.

Brian Clark
fuente
esto no es cierto y es fácil de probar, por favor elimine \ cambie esta respuesta
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