Julia :
Entonces, ¿quién cambió mi procedimiento ayer?Lesha :
no yoMaxim :
no yo-
Chicos, ¿podemos traer a Git?Seryozha :
ya es hora!Han pasado 2 semanas ...
Julia :
chicos?-
Yul, ¿no te comprometiste?Julia :
maldita sea no (...Así empezó todo. Bueno, ¿qué, cada personaje y cada línea se comprometen?
¿O tal vez todo esto sucederá solo?) En este punto, comienzan a venir a la mente
Se agregan
disparadores DDL ,
tabla temporal e imagen. Resuelto, almacenaremos versiones dentro
SQL Server'a !)

Primero, cree tablas en las que se almacenarán las versiones
USE master GO
Es importante tener en cuenta las limitaciones de la
tabla temporal.- Después de crearlos, no puede aplicar comandos DDL a las tablas principal o histórica. Y no puedes eliminar la tabla Temporal
- No puede cambiar datos en la tabla histórica
La segunda restricción nos conviene, pero ¿qué hacer con la primera?
El algoritmo es el siguiente:
Si bien aún no hay índices en la tabla, complételo con nuestros procedimientos, funciones, etc. marcados como
INIT , lo que en nuestro caso significará la colocación inicial
DECLARE @query NVARCHAR(MAX), @template NVARCHAR(MAX) = N' USE [db] INSERT INTO MASTER.dbo.VersionControl WITH (TABLOCKX) ( Event, Db, Sch, Object, Sql, Login ) SELECT ''INIT'' AS Event, DB_NAME(), ss.name AS Sch, so.name AS Object, CONCAT(''<query><![CDATA['', sasm.definition, '']]></query>'' ), SUSER_SNAME() AS Login FROM sys.objects AS so JOIN sys.schemas AS ss ON ss.schema_id = so.schema_id JOIN sys.all_sql_modules AS sasm ON sasm.object_id = so.object_id WHERE so.is_ms_shipped = 0 AND NOT EXISTS ( SELECT 1 FROM MASTER.dbo.VersionControl AS vc WHERE vc.Db = ''[db]'' AND vc.Sch = ss.name AND vc.Object = so.name ); '; DECLARE @databases TABLE (rn INT, Name sysname); INSERT @databases (rn, Name) SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn, name FROM sys.databases WHERE owner_sid != 0x01; DECLARE @i INT = 1, @max INT = (SELECT MAX(rn) FROM @databases), @error NVARCHAR(128), @db sysname; WHILE @i < @max BEGIN SELECT @query = REPLACE(@template, '[db]', Name), @db = Name FROM @databases WHERE rn = @i; BEGIN TRY EXECUTE sp_executesql @query; SET @i += 1; CONTINUE; END TRY BEGIN CATCH SET @error = CONCAT( 'XML Parsing error. In this case that''s mean one of [', @db, '] object is invalid for convert to XML' ); PRINT @error; SET @i += 1; CONTINUE; END CATCH; END; GO
Porque los cambios en los objetos se producirán con la
instrucción UPDATE , y con frecuencia veremos las versiones por clave: la base de datos, el esquema y el nombre del objeto, ¡el índice pide!
IF NOT EXISTS ( SELECT 1 FROM sys.indexes WHERE name = 'IX_VersionControl_upd_key' ) CREATE UNIQUE NONCLUSTERED INDEX IX_VersionControl_upd_key ON MASTER.dbo.VersionControl (Db, Sch, Object) INCLUDE (Sql, Event, Login);
Todo está listo para comenzar a almacenar versiones y nos ayudará con este
DDL TriggerImportante! Porque las tablas para las versiones están en la base de datos
maestra , después de crear un desencadenador, todos los que no tienen derechos sobre esta base de datos no pueden modificar, crear o eliminar objetos
IF EXISTS ( SELECT 1 FROM sys.server_triggers WHERE name = 'tr_VersionControl' ) DROP TRIGGER tr_VersionControl ON ALL SERVER GO CREATE TRIGGER tr_VersionControl ON ALL SERVER
Y para la conveniencia de usar este sistema, se propone el siguiente procedimiento.
Es fácil de usar El prefijo
sp_ nos ayudará a acceder al procedimiento sin especificar la base de datos y el esquema. Los parámetros se llenan intuitivamente. Puede especificar solo la base de datos y veremos objetos asociados solo con ella durante todo el tiempo, pero también puede usar el esquema, el objeto en sí mismo y, por supuesto, el rango de tiempo para el que se realizaron los cambios.
CREATE PROCEDURE dbo.sp_Vc @db sysname = '%', @sch sysname = '%', @obj sysname = '%', @from DATETIME2(0) = NULL, @to DATETIME2(0) = NULL AS BEGIN SET NOCOUNT ON; IF @from IS NULL AND @to IS NULL BEGIN SELECT * FROM master.dbo.VersionControl WHERE Db LIKE @db AND Sch LIKE @sch AND Object LIKE @obj ORDER BY StartDate DESC END ELSE BEGIN SELECT * FROM master.dbo.VersionControl FOR SYSTEM_TIME BETWEEN @from AND @to WHERE Db LIKE @db AND Sch LIKE @sch AND Object LIKE @obj ORDER BY StartDate DESC END END GO
A continuación se presentan ejemplos del uso del procedimiento.
Puede instalar este microframework desde mi
repositorio , y si su versión de SQL Sever es anterior a 2016,
aquí está . Por cierto, estamos usando esta versión ahora, pero no es tan genial.
En conclusión
Nunca logré vencer la conclusión
& _gt; y
& _lt; en lugar de los signos
> y
< de la tabla
master.dbo.VersionControl por el campo
SQL . Si puede ayudar con esto o tiene alguna idea, estoy esperando una
solicitud de extracción .
Gracias por su tiempo, ponga estrellas, corazones y flechas hacia arriba.