Um bom programa para quebra galho

Estava revirando uns arquivos no meu HD externo e achei um programa muito legal para

conexão ODBC.

Antes de falar do programa,,, a historinha…

Conheci uma vez uma empresa que o pessoal não deixava acessar o servidor com SQL por TS nem SSMS,,,

Perguntei pra eles como eu iria ajudar a identificar os problemas se não podia fazer muita coisa… me explicaram que era política da empresa, eu poderia acessar de qualquer outra forma, mas não poderia conectar meu note da rede nem instalar qualquer aplicativo na estação…

Foi com essa necessidade que conheci o ODBC QueryTool,,, ele é um programinha bem legal… de graça e funciona sem precisar instalar nada…

1_app

Você pode usar uma conexão existente de ODBC ou criar uma na hora…

2_connect

Como um quebra-galho para esse tipo de situação,,, acho que ele server para dar uma ajuda…

3_query

Você pode usar ele também para testar as conexões das estações cliente, com as restrições de usuário, restrições do SQL,,,

configurando o ODBC com as devidas informações, eu mostrei para um cliente como a aplicação iria se comportar com o fail-over das bases mirror.

Você pode baixar no site do SourceForge, ou no meu Skydrive, esse é um dos programas que vale a pena ter no pendrive.

T-SQL Tuesday #23 – Joins

Para o pessoal não ficar corrido entre escrever uns posts meia boca e se preocupar com os preparativos para o SQLPASS, o pessoal resolveu dar uma adiantada no T-SQL Tuesday desse mês,,,

Este mês ele é hospedado por Stuart Ainsworth (Blog | Twitter) e fala sobre joins..

Quer saber mais sobre Joins?

Vamos lá,,,

meu exemplo é bem simples,,, mostra os waits que estão acontecendo no SQL…

select
w.session_id,
w.wait_duration_ms,
w.wait_type,
w.blocking_session_id,
w.resource_description,
s.program_name,
t.text,
t.dbid,
s.cpu_time,
s.memory_usage
from sys.dm_os_waiting_tasks w
inner join sys.dm_exec_sessions s on
w.session_id = s.session_id
inner join sys.dm_exec_requests r on
s.session_id = r.session_id
outer apply sys.dm_exec_sql_text (r.sql_handle) t
where s.is_user_process = 1

Ele vai tentar associar a requisição ao wait.

Lync – Aparecer Offline

Quem usa software de mensagem instantânea sabe que tem a opção de aparecer invisível,,, e isso em muitos casos é bem útil…

Por padrão o Microsoft Lync não mostra essa opção, mas ela pode ser habilitada pelo administrador do Lync usando o comando de powershell:

Get-CSClientPolicy | Set-CSClientPolicy -EnableAppearOffline:$true

Isso tudo é uma linha só,,,

O usuário vai ter que desconectar e reconectar, ai a opção vai aparecer assim:

offline

Ai entra uma outra questão, por que, no ambiente corporativo, você não quer aparecer online ou com outro status para as pessoas?

Malditos SQL Aliases

Estava em um cliente montando uma estratégia para migração de 2 instâncias de SQL 2000 para uma única instância de SQL 2005… até aí tranquilo,,, certo?

Listamos os linked servers, jobs, usuários e senhas, bases, collation,,, etc,,, tudo quase pronto pra migração….

Ai, lembrei de um detalhe… algumas bases estavam em uma instância default do SQL,,, e vamos migrar todas para um SQL em uma instância,,, ai vem o problema:

  1. Aplicações antigas
  2. Algumas não possuem código fonte
  3. Outras precisam de projeto para alterar o fonte
  4. Muitas estações com o aplicativo
  5. etc..

Legal,,, iai? Só criar o SQL Aliases (Iniciar>Executar>Cliconfg)? boa,,, pena que tem que criar em maquina a maquina,,, Redirecionar DNS? até funcionaria se o outro SQL não tivesse instância. Poderíamos alterar o DNS e “adicionar o servidor” com o sp_addserver (sp_addserver ‘nome_do_host’, local, duplicate_ok) o problema é que a instância tem que escutar a 1433, até ai nenhum grande problema, adiciona como porta secundária.

como fazer o deploy de aliases rápido? Policy… cria uma chave de registro e adiciona o aliases…

  • “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo”
  • Nome:”Nome_do_alias”
  • Tipo: Sequencia
  • Valor: “DBMSSOCN,ServidorX\Instancia,1433”

Outra forma, utilizar um “proxy” de SQL,,, tipo F5, Green SQL,,,

TableDiff

Imagine a situação do post Corrompendo um Banco SQLmas na vida real,,,

Você chega um belo dia na empresa e, lê nos seus emails que, o SQL apresentou falha na estrutura de dados e algumas páginas de dados podem ter sido corrompidas,,,

Como um bom DBA, você corre para ver se o backup da noite foi feito, se os backups de transaction log também estão sendo feitos e descobre que sim,,,, todos os arquivos necessários para restaurar o banco estão lá,,,

Legal,,, mas,,, e agora? dependendo da utilização do banco você pode restaurar o backup da madrugada, os de log até o horário do problema e dali pra frente o que der pra fazer…

Em outros casos,,, você não pode se dar ao luxo de perder informação,,,,

Uma das formas seria executar o restore do banco em outro lugar, ou na mesma instância mas com outro nome, executar o checkdb e remover a página com problema e trazer a diferença dos dados,,, até aqui nada tão complicado,,, tirando o fato de se a tabela for muito grande, ou muito complexa e a query para mostrar essa diferença for muito complicado…

Para ajudar a resolver esse problema, o SQL possui uma ferramenta bem interessante chamada TableDiff.

O conceito dela é bem simples: Instância de origem, base de origem, tabela de origem, Instância de destino, base de destino, tabela de destino e o que você quer fazer…

Ex:

"C:\Program Files\Microsoft SQL Server\90\COM\tablediff.exe" -sourceserver MyServer1
                                                             -sourcedatabase MyDatabase1
                                                             -sourcetable MyTable1
                                                             -destinationserver MyServer1
                                                             -destinationdatabase MyDatabase1
                                                             -destinationtable MyTable2
                                                             -et DiffsTable

 

Nesse outro exemplo ele gera um arquivo com INSER/UPDATE/DELETE

"C:\Program Files\Microsoft SQL Server\90\COM\tablediff.exe" -sourceserver MyServer1
                                                             -sourcedatabase MyDatabase1
                                                             -sourcetable MyTable1
                                                             -destinationserver MyServer1
                                                             -destinationdatabase MyDatabase1
                                                             -destinationtable MyTable2
                                                             -et DiffsTable
                                                             -f d:\MyTable1_MyTable2_diff.sql

 

Simples certo? em teoria não é muito complicado…

Da pra deixar mais fácil? sim,,, com certeza…

O Sr. Mladen Prajdic (Blog | Twitter) desenvolveu uma interface bem interessante para ajudar na utilização do executável…

O link para download pode ser encontrado no post aqui, ou diretamente aqui.

O aplicativo é bem simples de usar, o ponto de atenção é que você precisa indicar onde está o executável do TableDiff.exe.

tablediffgui

Ele é bem auto-explicativo, pequeno e o principal,,, é de graça !!!

Vale gastar uns minutos para aprender a usar ele, vai que em um dia de emergência você precisa de uma ajuda rápida para solucionar um problema, ou ver a diferenças nas tabelas do seu logshipping….

Catalogar objetos

Esse código faz parte daquele tipo de código para gerar documentação.

Não faz nada muito complexo, apenas mostra o objeto, quem é dono, que tipo e quando foi criado.

SELECT   [NAME]          AS OBJECT_NAME,
           USER_NAME(UID)  AS OWNER,
           TYPE = CASE
                    WHEN XTYPE = 'u' THEN 'table'
                    WHEN XTYPE = 'c' THEN 'check constraint'
                    WHEN XTYPE = 'd' THEN 'default constraint'
                    WHEN XTYPE = 'f' THEN 'foreign key constraint'
                    WHEN XTYPE = 'fn' THEN 'scalar function'
                    WHEN XTYPE = 'if' THEN 'inline table function'
                    WHEN XTYPE = 'p' THEN 'stored procedure'
                    WHEN XTYPE = 'pk' THEN 'primary key'
                    WHEN XTYPE = 'tf' THEN 'table function'
                    WHEN XTYPE = 'tr' THEN 'trigger'
                    WHEN XTYPE = 'uq' THEN 'unique constraint'
                    WHEN XTYPE = 'v' THEN 'view'
                  END,
           CRDATE          AS CREATION_DATE
  FROM     SYSOBJECTS
  WHERE    XTYPE IN ('u','c','d','f',
                     'fn','if','p','pk',
                     'tf','tr','u','uq',
                     'v')
ORDER BY XTYPE

 

Estou fazendo index scan sim, idaí?

Complementando o Post Procurando por conversão implícita sobre a apresentação do Marcos Freccia (Blog | Twitter)  “10 coisas que todo desenvolvedor deveria saber sobre SQL Server

Um dos grandes problemas dessa conversão é o SQL utilizar index scan ao invés de index seek.

Esse código mostra consultas que estão executado Index Scan por motivos de Conversões Implícitas.

with XMLNAMESPACES
('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql)
select
total_worker_time/execution_count AS AvgCPU
, total_elapsed_time/execution_count AS AvgDuration
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads
, execution_count
, SUBSTRING(st.TEXT, (qs.statement_start_offset/2)+1 , ((CASE
qs.statement_end_offset WHEN -1 THEN datalength(st.TEXT) ELSE
qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS txt
, qs.max_elapsed_time
, db_name(qp.dbid) as database_name
, quotename(object_schema_name(qp.objectid, qp.dbid)) + N'.' +
quotename(object_name(qp.objectid, qp.dbid)) as obj_name
, qp.query_plan.value(
N'(/sql:ShowPlanXML/sql:BatchSequence/sql:Batch/sql:Statements/sql:StmtSimple[@StatementType = "SELECT"]/sql:QueryPlan/sql:RelOp/descendant::*/sql:ScalarOperator[contains(@ScalarString, "CONVERT_IMPLICIT")])[1]/@ScalarString', 'nvarchar(4000)' ) as scalar_string
, qp.query_plan
from sys.dm_exec_query_stats as qs
cross apply sys.dm_exec_query_plan(qs.plan_handle) as qp
cross apply sys.dm_exec_sql_text(qs.sql_handle) st
where qp.query_plan.exist(
N'/sql:ShowPlanXML/sql:BatchSequence/sql:Batch/sql:Statements/sql:StmtSimple[@StatementType = "SELECT"]/sql:QueryPlan/sql:RelOp/sql:IndexScan/descendant::*/sql:ScalarOperator[contains(@ScalarString, "CONVERT_IMPLICIT")]' ) = 1;

Gerador de Senhas

Esse é um código antigo que estava escondido no HD.

Bem simples e usual.

/*
Versao: 1.0
Data: 20100302
Por: Ricardo Leka
Site: https://leka.com.br
email: ricardo@leka.com.br
twitter: @bigleka
*/
/*
Gerador de Senhas
Pode gerar senhas com quantidades minima e maxima de caracteres
com numeros ou complexidade
*/
DECLARE
  @complex tinyint
  , @minlen tinyint
  , @maxlen tinyint  

SET @minlen = 4 --tamanho minimo da senha
SET @maxlen = 8 --tamanho maximo da senha
SET @complex = 4
-- 1 todas as letras minusculas
-- 2 inclui letras maiusculas
-- 3 inclui numeos
-- 4 inclui caracteres especiais

DECLARE
  @password varchar(12)
  , @len tinyint
  , @type  tinyint
  , @type2 tinyint

SET @len = 0
SET @password = ''
WHILE @len NOT BETWEEN @minlen and @maxlen
  BEGIN
    SET @len = ROUND(1 + (RAND(CHECKSUM(NEWID())) * @maxlen), 0) + 1
  END
WHILE @len > 0
  BEGIN
    DECLARE @newchar CHAR(1)
    SET @type = ROUND(1 + (RAND(CHECKSUM(NEWID())) * (@complex - 1)), 0)
    IF @type = 1
      SET @newchar = CHAR(ROUND(97 + (RAND(CHECKSUM(NEWID())) * 25), 0))
    IF @type = 2
      SET @newchar = CHAR(ROUND(65 + (RAND(CHECKSUM(NEWID())) * 25), 0))
    IF @type = 3
      SET @newchar = CHAR(ROUND(48 + (RAND(CHECKSUM(NEWID())) * 9), 0))
    IF @type = 4
      BEGIN
        SET @type2 = ROUND(1 + (RAND(CHECKSUM(NEWID())) * 3), 0)
        IF @type2 = 1
          SET @newchar = CHAR(ROUND(33 + (RAND(CHECKSUM(NEWID())) * 14), 0))
        IF @type2 = 2
          SET @newchar = CHAR(ROUND(58 + (RAND(CHECKSUM(NEWID())) * 6), 0))
        IF @type2 = 3
          SET @newchar = CHAR(ROUND(91 + (RAND(CHECKSUM(NEWID())) * 5), 0))
        IF @type2 = 4
          SET @newchar = CHAR(ROUND(123 + (RAND(CHECKSUM(NEWID())) * 3), 0))
      END
-- remove caracteres que podem ser confundidos com outros
    IF @newchar NOT IN ('b', 'l', 'o', 's', 'I', 'O', 'S', '0', '1', '!', '''', '.', ',', '/', '`', '\', '|')
      BEGIN
        SET @password = @password + @newchar
        SET @len = @len - 1
      END
  END
SELECT @password as Senha

[Vídeo] Instant File Initialization

Já vou logo avisando:

  • Não assista esse vídeo depois das 22h,,, não me responsabilizo por pesadelos,,,
  • Não assista perto dos seus filhos,,, é mais feio que o bicho papão,,,
  • Não assista no trabalho,,, seus colegas já sofrem tendo que trabalhar com você,,,,
  • Meu primeiro vídeo,,, Gravei o vídeo as 4am,,, estava com muito sono,,,

Se, depois de tudo isso, clicar em Play não me responsabilizo por absolutamente nada,,,

[vimeo http://www.vimeo.com/27824432 w=701&h=438]

Instant file initialization from Ricardo Leka on Vimeo.

1807

Atualmente meu notebook (também conhecido como desktop porque a bateria já era) não tem muita capacidade de suportar alguns testes,,, (Acer Aspire 5050 – AMD Turion 1 core, 1.9GB RAM, 35GB HD),,,

Então tentei fazer uma coisa interessante,,,, criar um banco e apontar os arquivos para meu storage (QNAP TS-110),,,

Tenho 2 instâncias de SQL instaladas nesse note, 1 SQL Server 2008 R2 e 1 SQL Server 2005.

Claro que no 2008 R2 funcionou e no 2005 não…

yep2008

nop

Ai lembrei que para o SQL 2005 (e para o 2008 sem ser R2) criar uma base em local UNC eu precisava habilitar a trace flag 1807. Feito isso conseguir criar a base sem problema.

yep

Achei interessante relembrar isso, pois vai que uma hora qualquer alguém precisa, ou para fazer um LAB ou por falta de espaço (meu caso) você sempre tem uma alternativa… e muita gente nem lembra dessa possibilidade…