Think Think .Net
Diego Nogare [MVP | MCT | MCITP | MCTS | MCP | INETA BR]

Como encontrar objetos do Database no SQL Server?

sábado, 15 maio 2010 05:36 by Nogare

Fala galera, essa semana, mais uma vez, precisei criar um script para uma documentação de sistema. Estamos montando algumas Matrizes de Rastreabilidade para um projeto no cliente e precisávamos saber todos os objetos que faziam parte de um determinado conjunto de tabelas. Como no código anterior (Como calcular a massa de dados no SQL Server?), a Engine que roda lá ainda é SQL Server 2000, e não temos muitas coisas que dê para fazer utilizando os recursos novos. O código original é pro SQL Server 2000 mas eu adaptei algumas poucas coisas rapidamente para o 2008. Essa execução abaixo é resultado do SQL Server 2008.

Neste caso, precisávamos encontrar todos os objetos que seriam documentados e, de acordo com a necessidade, migrado para a aplicação off-line que estamos atuando. Veja o código T-SQL e o resultado obtido.

O script é esse:

SET NOCOUNT ON

/* MOSTRAR TODAS TABELAS DO SCHEMA VENDAS [SALES] */
print('*********************************************************')
print('MOSTRAR TODAS TABELAS DO SCHEMA VENDAS [SALES]')

SELECT T.NAME 'TABELAS'
FROM sys.tables T
    INNER JOIN sys.schemas S
        ON T.schema_id = S.schema_id
WHERE S.name = 'Sales'
DECLARE @TABELA VARCHAR(50)
SET @TABELA = '%Store%'

/* RELACIONAMENTOS DE 1 NIVEL DA TABELA */
print('*********************************************************')
print('RELACIONAMENTOS DE 1 NIVEL DA TABELA')

SELECT PK.TABLE_NAME 'PAI',
       FK.TABLE_NAME 'FILHO'
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
    INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
        ON C.CONSTRAINT_NAME = PK.CONSTRAINT_NAME
    INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
        ON C.UNIQUE_CONSTRAINT_NAME = FK.CONSTRAINT_NAME
WHERE FK.TABLE_NAME = REPLACE(@TABELA,'%','')
   OR PK.TABLE_NAME = REPLACE(@TABELA,'%','')

/* TODOS OS OBJETOS DA TABELA */
print('*********************************************************')
print('TODOS OS OBJETOS DA TABELA')

SELECT O.NAME 'NOME',
       REPLACE(O.type_desc,'_',' ') 'TIPO'
FROM SYS.OBJECTS O
    INNER JOIN SYSCOMMENTS C
        ON O.object_id = C.ID
WHERE C.TEXT LIKE @TABELA

/* TODAS AS CONSTRAINTS DA TABELA */
print('*********************************************************')
print('TODAS AS CONSTRAINTS DA TABELA')

SELECT O2.NAME 'TABELA',
       CL.NAME 'COLUNA',
       O.NAME 'CONSTRAINT',
       COM.TEXT 'CONDIÇÃO'
FROM SYSCONSTRAINTS C
    INNER JOIN SYSOBJECTS O
        ON O.ID = C.CONSTID
    INNER JOIN SYSOBJECTS O2
        ON O2.ID = C.ID
    INNER JOIN SYSCOLUMNS CL
        ON CL.ID = O2.ID
        AND CL.COLID = C.COLID
    INNER JOIN SYSCOMMENTS COM
        ON O.ID = COM.ID
WHERE O2.NAME LIKE REPLACE(@TABELA,'%','')
  AND O2.XTYPE = 'U'
ORDER BY O2.NAME, CL.NAME, O.NAME

SET NOCOUNT OFF

e o resultado apresentado é esse:

*********************************************************
MOSTRAR TODAS TABELAS DO SCHEMA VENDAS [SALES]
TABELAS
--------------------------------
Store
StoreContact
ContactCreditCard
CountryRegionCurrency
CreditCard
Currency
SalesOrderDetail
CurrencyRate
Customer
SalesOrderHeader
CustomerAddress
SalesOrderHeaderSalesReason
SalesPerson
SalesPersonQuotaHistory
SalesReason
Individual
SalesTaxRate
SalesTerritory
SalesTerritoryHistory
ShoppingCartItem
SpecialOffer
SpecialOfferProduct

*********************************************************
RELACIONAMENTOS DE 1 NIVEL DA TABELA
PAI               FILHO
----------------- ----------------
StoreContact      Store
Store             Customer
Store             SalesPerson

*********************************************************
TODOS OS OBJETOS DA TABELA
NOME                     TIPO
------------------------ ---------------------------
uspLogError              SQL STORED PROCEDURE
iuIndividual             SQL TRIGGER
iStore                   SQL TRIGGER
vStoreWithDemographics   VIEW
ufnGetContactInformation SQL TABLE VALUED FUNCTION

*********************************************************
TODAS AS CONSTRAINTS DA TABELA
TABELA  COLUNA         CONSTRAINT             CONDIÇÃO
------- -------------- ---------------------- -----------
Store   ModifiedDate   DF_Store_ModifiedDate  (getdate())
Store   rowguid        DF_Store_rowguid       (newid())

Mais uma vez gostaria de ver os comentários de vocês falando sobre como fariam pra chegar a essas informações.

Como calcular a massa de dados no SQL Server?

terça-feira, 11 maio 2010 06:36 by Nogare

Fala galera, semana passada precisei fazer uma apresentação para o Comitê de IT do cliente que estou atuando. Essa apresentação tinha diversos pontos positivos de utilização de uma certa solução, e pra provar precisei mostrar alguns números. Foi necessário calcular a massa de dados (em tamanho) das informações que estavam sendo apresentadas e sincronizadas.

Para ficar claro o que precisamos fazer, vou tentar explicar superficialmente: O trabalho é pra sincronizar dados de uma aplicação OnLine (Web) com uma OffLine (Win) e o usuário trabalhar desconectado. A solução existente (não podemos mudar) realiza dois sincronismos: um na hora que o sistema é aberto a primeira vez e o segundo de tempos em tempos quando o usuário está conectado à Internet.

Bom, o pessoal do Comitê precisava saber o tamanho dos dados que seriam sincronizados no primeiro e no segundo momento. Então, criei um script e rodei em produção para me devolver essas informações. Por questões de sigilo dos dados, vou adaptar o script para rodar em cima do AdventureWorks e mostrar o resultado pra vocês. Com os dados reais fiz a consulta de 2009, mas pra esse exemplo utilizei 2003.

Gostaria de agradecer o Laerte Junior por me ajudar em um pedaço do script, eu mandei o código para ele e prontamente ele me respondeu com o pedaço que estava dando erro, corrigido! Se não fosse ele, eu teria perdido mais algumas horas. Tks brother!

Caso alguém não tenha o AdventureWorks, pode baixar gratuitamente.

SQL Server 2008: http://msftdbprodsamples.codeplex.com/releases/view/37109

SQL Server 2008 R2: http://msftdbprodsamples.codeplex.com/releases/view/24854

O script é esse:

SET NOCOUNT ON

/* Máximo de bytes do primeiro sincronismo */
print('*********************************************************')
print('Máximo de bytes do primeiro sincronismo [VENDAS]')

CREATE TABLE #TB_MASSA_TOTAL
(NAME varchar(100) null
,rows int
,reserved varchar(10)
,data varchar(10)
,index_size varchar(10)
,unused varchar(10))

CREATE TABLE #TB_EXECS
(CODIGO varchar(100))

INSERT INTO #TB_EXECS (codigo)
SELECT ' EXEC sp_spaceused N''Sales.' + name + ''';' from sysobjects where name like '%Sales%' and xtype = 'U'

DECLARE @SCRIPT VARCHAR(100)
DECLARE cr_cursor CURSOR
FOR SELECT codigo FROM #TB_EXECS
OPEN cr_cursor
FETCH NEXT FROM cr_cursor INTO @SCRIPT
WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO #TB_MASSA_TOTAL EXEC (@script)
        FETCH NEXT FROM cr_cursor INTO @script
    END

CLOSE cr_cursor
DEALLOCATE cr_cursor

SELECT (SUM(CONVERT(INT, REPLACE(reserved,' KB',''))) + SUM(CONVERT(INT, REPLACE(index_size,' KB',''))) ) / 1024 [MB]
      ,(SUM(CONVERT(INT, REPLACE(reserved,' KB',''))) + SUM(CONVERT(INT, REPLACE(index_size,' KB',''))) ) [KB]
      ,(SUM(CONVERT(INT, rows))) [LINHAS]
FROM #TB_MASSA_TOTAL

/* Qtd de Vendas em 2009 */
print('*********************************************************')
print('Qtd de Vendas em 2003')
select count(0) [Qtd]
from Sales.SalesOrderDetail s inner join
     Sales.SalesOrderHeader h
     on s.SalesOrderID = h.SalesOrderID
where h.OrderDate between '2003-01-01' and '2003-12-31'

/* Qtd de CPRs criadas em 2009 separadas por mês */
print('*********************************************************')
print('Qtd de Vendas em 2003 separadas por mês')
select case month(h.OrderDate)
        when 1 then '01 (Jan)'
        when 2 then '02 (Fev)'
        when 3 then '03 (Mar)'
        when 4 then '04 (Abr)'
        when 5 then '05 (Mai)'
        when 6 then '06 (Jun)'
        when 7 then '07 (Jul)'
        when 8 then '08 (Ago)'
        when 9 then '09 (Set)'
        when 10 then '10 (Out)'
        when 11 then '11 (Nov)'
        when 12 then '12 (Dez)' end [Mês], count(*) Qtd
from Sales.SalesOrderDetail s inner join
     Sales.SalesOrderHeader h
     on s.SalesOrderID = h.SalesOrderID
where h.OrderDate between '2003-01-01' and '2003-12-31'
group by month(h.OrderDate)
order by Mês

/* Máximo de qtd de Bytes (por linha) na tabela eCPR_CPR */
print('*********************************************************')
print('Máximo de qtd de Bytes (por linha) na tabela de Detalhes')
select (sum(c.length) / 8) [Bytes]
from syscolumns c
    inner join sysobjects o
on c.id = o.id
where o.name = 'SalesOrderDetail'

print('*********************************************************')
print('Máximo de qtd de Bytes (por linha) na tabela de Cabeçalho')
select (sum(c.length) / 8) [Bytes]
from syscolumns c
    inner join sysobjects o
on c.id = o.id
where o.name = 'SalesOrderHeader'

DROP TABLE #TB_MASSA_TOTAL
DROP TABLE #TB_EXECS

SET NOCOUNT OFF

e o resultado apresentado é esse:

*********************************************************
Máximo de bytes do primeiro sincronismo [VENDAS]
MB          KB          LINHAS
----------- ----------- -----------
32          32848       180675

*********************************************************
Qtd de Vendas em 2003
Qtd
-----------
51237

*********************************************************
Qtd de Vendas em 2003 separadas por mês
Mês      Qtd
-------- -----------
01 (Jan) 1227
02 (Fev) 1936
03 (Mar) 1487
04 (Abr) 1743
05 (Mai) 2641
06 (Jun) 2019
07 (Jul) 3600
08 (Ago) 7585
09 (Set) 7653
10 (Out) 5959
11 (Nov) 7085
12 (Dez) 8302

*********************************************************
Máximo de qtd de Bytes (por linha) na tabela de Detalhes
Bytes
-----------
15

*********************************************************
Máximo de qtd de Bytes (por linha) na tabela de Cabeçalho
Bytes
-----------
65

Em posse dessas informações consegui apresentar os dados necessários para o comitê de IT do cliente que ficou impressionado com o “detalhe” das informações. Eles esperavam algo superficial, e com o resultado apresentado, ficaram super satisfeitos e contentes (e ganhamos pontos para fechar mais projetos).

Gostaria de ver nos comentários de vocês outras formas que encontraram para chegar a um resultado destes.