Por lo que parece que está utilizando varios esquemas para transmitir la información de la tienda, manteniendo los nombres de objetos consistentes, w/un esquema por tienda, ¿verdad? Y algún tipo de conexión/magia del usuario para que las consultas lleguen a las vistas correctas.
Si es así, presento dos atroces hacks y una solución recomendada (para que conozca sus opciones).
Egregio truco # 1, asume el punto de vista de tienda incluyen todas las columnas de la tabla base excepto StoreID, en la misma posición ordinal como la tabla de base, y no hay otras columnas:
CREATE TRIGGER tr_Tenant_fluff ON AcmeBatWings.data
INSTEAD OF INSERT
AS BEGIN
DECLARE @StoreId INT
SELECT @StoreId = StoreId FROM dbo.StoreSchemas
WHERE StoreSchema = OBJECT_SCHEMA_NAME(@@PROCID)
INSERT dbo.data SELECT *, @StoreId FROM inserted
END
Si si alguna vez agrega una columna a la tabla base, deberá actualizar todas las vistas de tienda para incluir la columna, o los desencadenadores se romperán.
Egregio truco # 2, asume el mismo que (1), excepto que StoreID está incluido en las vistas tienda:
CREATE TRIGGER tr_Tenant_fluff ON AcmeBatWings.data
INSTEAD OF INSERT
AS BEGIN
DECLARE @StoreId INT
SELECT @StoreId = StoreId FROM dbo.StoreSchemas
WHERE StoreSchema = OBJECT_SCHEMA_NAME(@@PROCID)
SELECT * INTO #inserted FROM inserted
UPDATE #inserted SET StoreId = @StoreId
INSERT dbo.data SELECT * FROM #inserted
END
Los beneficios de truco # 2 más de truco # 1 es que se puede defina las vistas de su tienda con SELECT *
, y si las tablas base cambian, simplemente recompila todas las vistas de tienda con sp_refreshview
. La desventaja es que está copiando datos insertados de una tabla intermedia a otra, y actualizando la segunda tabla. Esto triplicó la sobrecarga de tu disparador INSTEAD OF INSERT
, que ya era bastante caro para empezar. es decir,
- overhead base del
INSTEAD OF INSERT
gatillo -> costo para poblar inserted
->x
.
- costo para poblar
#inserted
de inserted
-> alrededor de x
.
- costo para actualizar
#inserted
-> acerca x
- sobrecarga total de truco atroz # 2: alrededor de 3
x
Así lo contrario, lo mejor que puede hacer es la escritura de los factores desencadenantes fuera. Es un proceso bastante directo, una vez que esté familiarizado con las tablas del sistema, y puede modificar la generación de activadores de la forma que considere más conveniente. Para el caso, también deberías escribir las vistas de la tienda.
Para empezar:
CREATE TABLE dbo.data (Name VARCHAR(10), StoreId INT)
GO
CREATE SCHEMA StoreA
GO
CREATE SCHEMA StoreB
GO
CREATE SCHEMA StoreC
GO
CREATE VIEW StoreA.data AS SELECT Name FROM dbo.data WHERE StoreId = 1
GO
CREATE VIEW StoreB.data AS SELECT Name FROM dbo.data WHERE StoreId = 2
GO
CREATE VIEW StoreC.data AS SELECT Name FROM dbo.data WHERE StoreId = 3
GO
CREATE TABLE dbo.StoreSchemas (StoreSchema SYSNAME UNIQUE, StoreId INT PRIMARY KEY)
GO
INSERT dbo.StoreSchemas VALUES ('StoreA', 1), ('StoreB', 2), ('StoreC', 3)
GO
DECLARE @crlf NCHAR(2) = NCHAR(13)+NCHAR(10)
SELECT
N'CREATE TRIGGER tr_Tenent_fluff ON '+schema_name(v.schema_id)+N'.data'[email protected]
+ N'INSTEAD OF INSERT'[email protected]
+ N'AS BEGIN'[email protected]
+ N' INSERT dbo.data ('
+ STUFF((
SELECT @crlf+N' , '+name FROM sys.columns tc
WHERE tc.object_id = t.object_id
AND (tc.name IN (SELECT name FROM sys.columns vc WHERE vc.object_id = v.object_id)
OR tc.name = N'StoreId')
ORDER BY tc.column_id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
,5,1,N' ')[email protected]
+ N' )'[email protected]
+ N' SELECT'
+ STUFF((
SELECT @crlf+N' , '+name
+ CASE WHEN name = N'StoreId' THEN ' = '+(
SELECT CONVERT(NVARCHAR,StoreId) FROM dbo.StoreSchemas s
WHERE s.StoreSchema = SCHEMA_NAME(v.schema_id)
)
ELSE '' END
FROM sys.columns tc
WHERE tc.object_id = t.object_id
AND (tc.name IN (SELECT name FROM sys.columns vc WHERE vc.object_id = v.object_id)
OR tc.name = N'StoreId')
ORDER BY tc.column_id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
,5,1,N' ')[email protected]
+ N' FROM inserted'[email protected]
+ N'END'[email protected]
+ N'GO'[email protected]
FROM sys.tables t
JOIN sys.views v
ON t.name = v.name
AND t.schema_id = SCHEMA_ID('dbo')
AND v.schema_id <> t.schema_id
WHERE t.name = 'data'
GO
Usted mencionar que el sistema es multi-tenant; ¿Planeabas codificar con fuerza un valor de '99' para todos tus factores desencadenantes o el StoreId dependería de quién está usando el sistema? Además, ¿qué versión de SQL Server? – LittleBobbyTables
¿Está diciendo que tiene vistas diferentes para cada inquilino que hace referencia a la misma tabla base y la única diferencia es que tienen un filtro de identificación diferente? –
la vista y el activador no están alineados en su ejemplo. En la vista, AcmeBatWings es un nombre de esquema. En el disparador, es un nombre de objeto. ¿Cuál es? Un nombre de esquema, supongo. Eso hace una gran diferencia. –