terça-feira, 24 de novembro de 2009

Gerando script das views para suas tabelas

Bom dia pessoal.

Hoje eu estava trabalhando em um cliente e precisei fazer uma coisa bem manual: Criar uma série de views com um nome diferente da tabela que estamos consultando, mas contendo todos os campos da tabela original.
Qual o motivo disso? Nós estamos criando um ambiente temporário onde estou jogando um monte de informações e vamos expor uma "interface" usando visões, que o usuário de negócio vai poder consultar à vontade e eventualmente criar consultas e relatórios. Então usaremos essa abstração, que nesse momento refletirá boa parte das tabelas, para evitar um pouco de retrabalho e atrito entre os lados, caso a estrutura mude, e dividir bem a questão de segurança.

Agora que vocês estão contextualizados vamos ver o que bolei... Eu poderia simplesmente sair escrevendo umas 50 visões com todos os campos, mas isso iria levar um tempão, então montei um script rápido que me ajudaria a gerar o código que preciso.

Seu mecanismo básico é o seguinte: tenho uma tabela temporária com N registros contendo o nome do esquema, da tabela existente e o nome que quero dar para a view. Bom base nessa tabela eu utilizo o CROSS APPLY para gerar uma string usando informações da sys.objects, sys.columns e sys.schemas, usando o truque com XML que já coloquei aqui no blog (http://luticm.blogspot.com/2009/06/gerar-registros-em-forma-de-colunas.html).

Segue o código T-SQL utilizando o AdventureWorks2008 para vocês brincarem e, quem sabe, utilizarem em algum momento, customizando o que será gerado.

USE AdventureWorks2008
go

WITH TabelaView AS
(SELECT Esquema, Tabela, Visao
FROM ( VALUES
('Sales', 'SalesOrderHeader', 'Venda'),
('Sales', 'SalesOrderDetail', 'DetalheVenda'),
('Production', 'Product', 'Produto'))
AS T(Esquema, Tabela, Visao))

SELECT
CodigoViews.Instrucao
FROM TabelaView
CROSS APPLY
(SELECT
'
IF OBJECT_ID(''vw_'+ TabelaView.Visao +''') IS NOT NULL
DROP VIEW dbo.[vw_'+ TabelaView.Visao +']
go

CREATE VIEW dbo.vw_' + TabelaView.Visao + '
WITH SCHEMABINDING
AS
SELECT ' +
STUFF(
(SELECT N', ' + QUOTENAME(SC.name) AS [text()]
FROM SYS.columns AS SC
INNER JOIN sys.objects AS SO
ON SO.object_id = SC.object_id
INNER JOIN sys.schemas AS SS
ON SO.schema_id = SS.schema_id
WHERE SO.type = 'U'
AND SO.name = TabelaView.Tabela
AND SS.name = TabelaView.Esquema
FOR XML PATH('')), 1, 2, N'') + '
FROM ' + TabelaView.Esquema + '.' + TabelaView.Tabela + '
go'
AS Instrucao) AS CodigoViews
go

E o código gerado é esse aqui:

IF OBJECT_ID('vw_Venda') IS NOT NULL
DROP VIEW dbo.[vw_Venda]
go

CREATE VIEW dbo.vw_Venda
WITH SCHEMABINDING
AS
SELECT [SalesOrderID], [RevisionNumber], [OrderDate], [DueDate], [ShipDate], [Status], [OnlineOrderFlag], [SalesOrderNumber], [PurchaseOrderNumber], [AccountNumber], [CustomerID], [SalesPersonID], [TerritoryID], [BillToAddressID], [ShipToAddressID], [ShipMethodID], [CreditCardID], [CreditCardApprovalCode], [CurrencyRateID], [SubTotal], [TaxAmt], [Freight], [TotalDue], [Comment], [rowguid], [ModifiedDate]
FROM Sales.SalesOrderHeader
go

IF OBJECT_ID('vw_DetalheVenda') IS NOT NULL
DROP VIEW dbo.[vw_DetalheVenda]
go

CREATE VIEW dbo.vw_DetalheVenda
WITH SCHEMABINDING
AS
SELECT [SalesOrderID], [SalesOrderDetailID], [CarrierTrackingNumber], [OrderQty], [ProductID], [SpecialOfferID], [UnitPrice], [UnitPriceDiscount], [LineTotal], [rowguid], [ModifiedDate]
FROM Sales.SalesOrderDetail
go

IF OBJECT_ID('vw_Produto') IS NOT NULL
DROP VIEW dbo.[vw_Produto]
go

CREATE VIEW dbo.vw_Produto
WITH SCHEMABINDING
AS
SELECT [ProductID], [Name], [ProductNumber], [MakeFlag], [FinishedGoodsFlag], [Color], [SafetyStockLevel], [ReorderPoint], [StandardCost], [ListPrice], [Size], [SizeUnitMeasureCode], [WeightUnitMeasureCode], [Weight], [DaysToManufacture], [ProductLine], [Class], [Style], [ProductSubcategoryID], [ProductModelID], [SellStartDate], [SellEndDate], [DiscontinuedDate], [rowguid], [ModifiedDate]
FROM Production.Product
go


Notem que o T-SQL é bem simples e fácil de ser alterado, então se eu quisesse omitir colunas do tipo uniqueidentifier ou remover campos com nome CodigoXXXXXXX, basta adicionar algumas cláusulas where no código.

Post rápido, mas espero que seja útil para alguém. Ou então pelo menos a idéia do T-SQL...
Você pode baixar o script aqui.

[]s
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer
Sr. Nimbus Serviços em Tecnologia Ltda
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm

Nenhum comentário:

Postar um comentário