Category Archives: TI

SQL Saturday #245 – Rio de Janeiro

Teremos um grande evento da comunidade SQL no Brasil…. o SQL Saturday #245

O SQL Saturday é totalmente gratuito e focado em SQL Server, um dia inteiro de palestras técnicas. No momento o evento encontra-se com o Call for Speakers aberto, ou seja, recebendo inúmeras propostas de palestras, tendo até agora já recebido propostas de palestrantes de vários locais do Brasil e inclusive de outros países !!!

Trata-se da 2a edição do evento, que ocorreu com muito sucesso em abril de 2012, contando na época com mais de 300 participantes.

SQL Saturday é uma marca de eventos já conhecida mundialmente pela alta qualidade técnica. A marca pertence a uma organização chamada SQL PASS, cujo trabalho envolve apoiar grupos de usuários de SQL Server – denominados de PASS Chapter – por todo o mundo.

O SQL PASS cede a marca, bem como algumas ferramentas on-line, patrocinio e orientação para que o PASS Chapter da região realize o evento. No Rio de Janeiro o evento está sendo realizado pelo PASS Chapter devSQL, o mais antigo PASS Chapter do Brasil, liderado por Dennes Torres (t | b).

As inscrições para o evento estão abertas e, como citado antes, é totalmente gratuito. Trata-se do 2o evento realizado no Brasil. O primeiro, realizado em São Paulo por outro PASS Chapter, ficou totalmente lotado antes mesmo da grade de palestras ser definida.

Evento : SQL Saturday #245 – Rio de Janeiro

Data : 31/08

Horário : Abertura as 08:00hs, inicio das palestras as 09:00hs até as 18hs

Local : Universidade Veiga de Almeida

Endereço : Rua Ibituruna, 108, tijuca, próximo a estação São Cristóvão do metrô

Site do Evento : http://www.sqlsaturday.com/245/eventhome.aspx

Executar teste de MX usando Powershell

Algumas vezes ajudo o pessoal de mensageria a arrumar algumas configurações de DNS ou procurar as causas de um anti-spam ter ou não bloqueado alguma mensagem,,,

Basicamente tudo começa com a análise do cabeçalho da mensagem e as configurações de DNS do remetente…

O processo em sí é bem simples, mas toma um tempo em ficar fazerndo as pesquisas de DNS como conectar em um servidor de DNS, ver se o domínio é valido, se tem SPF se tem MX, se o IP do MX é um A válido, etc. etc. etc….

resolvi diminuir um pouco esse trabalho e montei um script em Powershell para ajudar a fazer uma parte dessas consultas…

ele não está 100%,,,, ainda apresenta uma ou outra falha dependendo do domínio,,, mas já ajuda em uns 90% dos casos…

#domínio que você quer consultar
$procurar = "leka.com.br"

#servidor de DNS que utilizaremos para consulta do DNS
$DNSserver = "4.2.2.2"

#localiza os registros de MX do domínio
$MXs = Resolve-DnsName $procurar -Type MX -Server $DNSserver | Select-object -ExpandProperty NameExchange

#localiza o registro TXT para ajudar a ver o SPF
$TXT = Resolve-DnsName $procurar -Type TXT -Server $DNSserver | Select-object -ExpandProperty Strings

Write-Host Consultas utilizando = $DNSserver
Write-Host $procurar
Write-Host SPF = $TXT

foreach($MX in $MXs)
{
#Verifica se o registro de MX possui uma entrada A
$IPA = Resolve-DnsName $MX -Type A -Server $DNSserver #| Select-Object -ExpandProperty IP4Address
foreach($IP in $IPA.IP4Address)
{

#Verifica se o IP da entrada A possui um reverso tipo A
$PTR = Resolve-DnsName $IP -Type PTR -Server $DNSserver | Select-Object -ExpandProperty NameHost

#Verifica se o A do reverso é valido
If(Resolve-DnsName "$PTR" -type A -Server $DNSserver )
{
$ok = $IPA.Name, $IP, $PTR
$ok | Select-Object @{N="MX";E={$IPA.Name}}, @{N="IP";E={$IP}}, @{N="Reverso";E={$PTR}}, @{N="Status";E={"A Valido"}} -Unique
}
else
{
$falha = $IPA.Name, $IP, $PTR
$ok | Select-Object @{N="MX";E={$IPA.Name}}, @{N="IP";E={$IP}}, @{N="Reverso";E={$PTR}}, @{N="Status";E={"A Invalido"}} -Unique
}
}

}

A idéia é bem simples:

  • coloca-se o domínio que vamos pesquisar e um servidor de DNS que será usado para executar a pesquisa das informações..
  • verifico se existe MX para esse domínio
  • localizo a entrada TXT e você vê as configurações de SPF, não sabe o que é SPF ? leia um pouco aqui.
  • Verifico que o MX tem um registro A
  • Verifico se IP do registro A tem um PTR (DNS reverso)
  • testo se o PTR aponta para um A válido.

Ainda estou trabalhando para melhorar o tratamento de erro em algumas partes do script, mas só isso já ajuda a identificar alguns problemas…

Para uma próxima versão espero conseguir fazer testes de relay e fazer uma análise entre os registros de SPF e os IP´s informados de MX para saber se são validos… mas isso está sendo um pouco mais complicado….

Procurar por arquivos duplicados usando PowerShell

Um colega de trabalho estava precisando de ajuda para vasculhar em disco com 1TB por arquivos repetidos para poder apagar…

existem vários programas gratuitos que fazem isso,,

mas, vamos fazer da forma mais legal… o bom e velho PowerShell…

a idéia é pegar e comparar o Hash de MD5 dos arquivos e mostrar apenas quando aparecerem mais de uma vez…

Para deixar simples, na linha 3 troque para o diretório que você quer que ele pesquise.

Na linha 4 coloque o local e o arquivos onde o resultado será salvo

ele vai armazenar o nome do arquivo, locallização completa, data da criação, data da modificação, tamanho e o Hash do MD5.

depois você pode editar o arquivo no excel e escolher quais quer deixar e os que você vai apagar…


function get-md5hash {[System.BitConverter]::ToString((new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash([System.IO.File]::ReadAllBytes($args)))}

$procurar = "e:\teste"
$resultado = "e:\teste\teste.csv"
Get-ChildItem $procurar -Recurse|`
?{!$_.psiscontainer}|`
Select-Object Name,Fullname,CreationTime,LastWriteTime,Length,@{Name="MD5";Expression={Get-md5hash $_.fullname}}|`
group MD5|?{$_.Count -gt 1}|%{$_.Group}|sort MD5|`
Export-Csv $resultado -NoTypeInformation -Encoding "Unicode"

Vamos estressar memória

Vamos estressar um pouco de memória?

Seguindo a mesma idéia do post anterior, esse script em powershell server para estressar memória, gerando alocação em variável de letras ‘a’ em blocos de 128MB.

Dependendo da sua configuração, isso pode gerar grande stress de disco na unidade onde o page file está alocado…


$mem_total =[int](
Get-WMIObject -class Win32_PhysicalMemory |
Measure-Object -Property capacity -Sum |
ForEach-Object {[math]::round(($_.Sum / 1GB - 2),2)}) #memoria total da maquina –2GB
$mem_stress = @()
$mem_loop = $mem_total * 8 #multiplica pq o tamanho da alocacao e 128mb
$i = 0
while ($i -le $mem_loop)
{

$mem_stress + ("a" * 128MB)
Start-Sleep -s 1
write-host $i
$i++
}

Basicamente não precisa deixar rodar até o final,,, apenas comece e pare a execução,,,

na pior das situações você terá que finalizar o processo do powershell pelo gerenciador de tarefas,,,

sempre lembrando,,, quer emoção? faça em produção,,,, depois não reclama se alguém brigar com você…

Vamos estressar processador

Estava eu,,, feliz e sorridente,,, serelepe…. fazendo minhas monitorações… e o pessoal chegou com uma nova maquina para substituir um hardware antigo de SQL…

o pessoal tinha acabado de instalar o W2k8 R2 e pediu para eu testar o processador,, só pra saber se a maquina estava bem e se ela esquentava muito…

horas,,, por que não? claro… vamos brincar….

ForEach ($Numero in 1..64){ #altera para a quantidade de núcleos de processador, ou na dúvida multiplica por 2 da quantidade total
start-job -ScriptBlock{
$resultado = 1; foreach ($numero in 1..2147483647) {$resultado = $resultado * $numero}
}
}
Start-Sleep -s 5 #quantidade de tempo, em segundos, da duração do teste
get-job | stop-job

se você abrir o gerenciador de tarefas vai perceber que aparecerão diversos processos do PowerShell e eles vão começar a consumir processador….
Se tudo der certo, após o tempo que você determinou, ele deve parar de executar,,, mas caso aconteça algum problema, comece a matar os processos…

vale o lembrete… Não faça isso em produção… a não ser que você queira emoção…

Converter a instalação x86 em x64 do SQL 2008R2/2012

pinoquioAcho que uma das piores coisas é chegar em um cliente e ver que ele tem recurso de Hardware mas alguém fez a infelicidade de instalar o SQL x86 ao invés de instalar a opção x64…

Isso porque o cara tem que escolher explicitamente a instalação x86,,,

Aí você pergunta para o infeliz o motivo da escolha e ele responde que ou não sabe a diferença, ou que como o sistema dele é todo x86 ele instalou o banco desta forma para manter compatibilidade…

bom,,, não importa qual a desculpa,,, tem uma forma de alterar a instalação feita e converter o executável do serviço de x86 para x64,,,

para SER BEM CLARO não faça isso no seu ambiente de produção SEM TESTAR antes,,, é por sua total conta e risco…

vamos usar o powershell para executar uma chave encriptada,,, essa chave vai alterar algumas informações de chaves de registro que o executável do serviço do SQL utiliza para carregar os binários para o SQLOS .

$Key = (1..16)
$chave = ('76492d1116743f0423413b16050a5345MgB8ADYANwBTAEIAegBrADQASwBQAFEAKwBjAEUAMABaAE0AdgBiAFIARABMAEEAPQA9AHwANwAyADIANQBkADMANABjADUAYQAwAGUAMgAxADEAYQA1AGQAYQAyADIANAAwADYAYwAyADIAMQAwADIAZQA5AGMAOAA2ADAAZgA0ADIAOABlAGIAYwBlADEAYQA1AGIAZQBhADcAYgA5ADEAZAA3AGIAYQA4ADQAYwA3ADMAYQA=')
$chave1 = convertto-securestring $chave -key $key
Start-Sleep -s 5
$a = new-object -comobject wscript.shell
$b = $a.popup([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($chave1)),0,”Conversao de x32 para x64”,1)
(new-object -com SAPI.SpVoice).speak($chave1)

Boas modificações !!!

Erros nas descrições de eventos do SQL no event viewer

Algumas vezes procurando por erros nos eventos de sistema, já me deparei com uma mensagem de informação bem estranha:

MSSQLSERVER Information System Event 17055 <SQL server Instance Name > “The description for Event ID ( 17055 ) in Source ( MSSQLSERVER ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: 18265, Log backed up: Database: Database Name, creation date(time): 2012/07/11(09:38:17), first LSN: 720:282:1, last LSN: 720:282:1, number of dump devices: 1, device information: (FILE=1, TYPE=DISK: {‘\\ServerLog02\BACKUP\Backup123.TRN’}).

Eu sei que não é um erro de backup, se procurar os MSDB ou no job de backup não tem nenhum erro na geração do arquivo e o arquivo está no devido local.

Isso acontece porque o Event Viewer não consegue interpretar a mensagem colocada pelo SQL nos registros de eventos… A causa mais provável é que o caminho da biblioteca que passa a informação de como o Event Viewer deve interpretar a informação gravada está no lugar errado…

Como fazer para corrigir isso? até que é bem simples…

  1. Localize onde o SQL está instalado, procure dentro do diretório BINN um diretório chamado Resources e dentro dele outro diretório chamado 1033
  2. Dentro deste diretório deve existir um arquivo chamadq sqlevn7.rll.
  3. Abra o Editor de Registro (regedit), procure pela chave [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MSSQLServer] ou [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MSSQL$INSTANCE_NAME] em INSTANCE_NAME localize o nome da sua instância.
  4. Do lado da direita localize uma entrada do tipo REG_SZ com o nome EventMessageFile
  5. Compare o caminho para o diretório do arquivo sqlevn70.rll em relação ao local onde você localizou o arquivo na sua instalação, provavelmente são diferentes…
  6. Faça um backup da chave de registro.
  7. Substitua o caminho da chave EventMessageFile pelo caminho onde você localizou o arquivo sqlevn7.rll na sua instalação.
  8. Feche e abra o Event Viewer,,,
  9. Localize o evento que antes estava como o exemplo acima,,, e você terá a informação sendo mostrada corretamente.

Isso se aplica a SQL 2000, 2005 e 2008,, ainda não tive esse tipo de problema com o 2012

Desafio Tabuada em TSQL

Comecei alguns desafios com a equipe de banco da empresa pedindo algumas soluções para um problema…

Semana passada eles tinham que entregar um código que mostra-se uma tabuada… mas haviam algumas premissas:

  1. Eu poderia escolher de qual a qual número. Ex.: tabuada do 2 ao 10 ou do 5 ao 20…
  2. em todos os casos o resultado deveria ser um texto que possuísse o símbolo de multiplicação X e o sinal de igual =…

O pessoal se empenhou e vieram com códigos interessantes…

um deles foi:

DECLARE @InicNum int, @FimcNum int
SET @InicNum = 5
SET @FimcNum = 7
;WITH numeros AS (
 SELECT number AS N
 FROM master..spt_values
 WHERE type = 'P'
 AND number BETWEEN CAST(@InicNum AS varchar) AND CAST(@FimcNum AS varchar)
),
F1 AS(
select number as N from spt_values
where type = 'P'
AND number BETWEEN 1 AND 10
),
produto AS (
 SELECT
 M = n2.N,
 F = n1.N,
 P = n1.N * n2.N
 FROM F1 n1
 CROSS JOIN numeros n2
)
SELECT cast(M as varchar(2)) + ' x ' + cast(F as varchar(2)) + ' = ' + cast(P as varchar(3))
FROM produto
order by M

outra opção:

DECLARE @CALC1 INT, @CALC2 INT
DECLARE @NUM1 VARCHAR(500), @NUM2 VARCHAR(500) , @RESTO VARCHAR(500), @LINHA NVARCHAR(500)
SET @CALC1 = 1
WHILE @CALC1 &lt;= 10 -- AQUI

BEGIN
 SET @LINHA = @CALC1
 SELECT '&quot; TABUADA DO ' + CONVERT(VARCHAR(15),@LINHA) + ' &quot;'
 SET @CALC2 = 1
 WHILE @CALC2 &lt;= 10 --
 BEGIN
 SET @NUM1 = @CALC1
 SET @NUM2 = @CALC2
 SET @RESTO = @CALC1 * @CALC2
 SELECT @NUM1 + 'X' + @NUM2 + ' = ' + @RESTO AS 'TABUDA'
 SET @CALC2 = @CALC2 + 1
 END
 SET @CALC1 = @CALC1 + 1
END

Mais uma…

SET nocount on
go
declare @i int
set @i = 3
declare @f int
set @f = 20
declare @1 int set @1 = 1
declare @2 int set @2 = 2
declare @3 int set @3 = 3
declare @4 int set @4 = 4
declare @5 int set @5 = 5
declare @6 int set @6 = 6
declare @7 int set @7 = 7
declare @8 int set @8 = 8
declare @9 int set @9 = 9
declare @10 int set @10 = 10
WHILE @i &lt;= @f
BEGIN
BEGIN
SELECT convert(varchar(2),@1)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@2)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@3)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@4)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@5)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@6)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@7)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@8)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@9)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
SELECT convert(varchar(2),@10)+'x'+convert(varchar(20),@i)+'='+convert(varchar(20),@i)
END
SET @i = @i + 1
END

E a última…

declare @i int
declare @y int
declare @num varchar(max)
declare @num2 varchar(max)
declare @res varchar(max)

-- Atribui @y = Tabuada começa do 1 -
set @y=1
-- Enquanto @y menor ou igual a 10, vai ate tabuada do 10 -
while @y&lt;=10
-- Inicio 1
begin
 -- Atribui @i = 1 começa com x 1, no caso 1 x 1 ou então(@y x @i )
 set @i=1
 -- Enquanto @i menor ou igual a 10 - vai ate x 10
 while @i&lt;=10
 -- Inicio 2
 begin
 -- Atribui @num = @i
 set @num = @i;
 -- Atribui @num2 = @y
 set @num2 = @y;
 -- Atribui @res = @y * @i
 set @res = @y*@i
 -- Mostrando o Resultado da tabuada concatenando os resultados -
 print @num2+'x'+@num+'='+@res
 -- Atribui @s a ele mesmo + 1, 'próximo valor de @s' - soma para ir ao próximo numero -
 set @i=@i+1
 -- Inicio 2
 end
 -- Atribui @y a ele mesmo + 1, 'próximo valor de @y' - soma para ir a proxima tabuada -
 set @y=@y+1
 -- Imprime enter e '---------' enter - só o espaçamento entre tabuadas
 print Char(13)+'----'+Char(13)
-- Fim Inicio 1
end

Maldito seja Case Sensitive

Apenas para deixar claro: Não sou contra a utilização de CS e AS.

O desenvolvedor tem que lembrar que quando a base está com o collation em CS e ninguém alterou a coluna da pesquisa para CI ele vai ter resultados diferentes quando usa essa coluna em um distinct ou no where…

A algum tempo um desenvolvedor veio conversar comigo porque ele estava tendo problemas em um resultado de um select,,, coisa pouca, em uma tabela de uns 1kk de registros ele queria usar distinct para recuperar umas informações, quando ele usava o order by ele mostrava muitos resultados parecidos…

Lembrei ele que a base era CS e que ou teria que usar UPPER/LOWER ou passar um collation para a coluna da pesquisa ele ficou me olhando como se eu fosse louco…. ta certo,,, ele não estava errado,,, mas era uma solução rápida e indolor…

Exemplo:

CREATE DATABASE [BDTESTE]
COLLATE Latin1_General_100_CS_AS
GO

USE BDTESTE
GO

create table tbl_teste(
nome varchar(20)
)
insert into tbl_teste
select 'teste'
union
select 'Teste'
union
select 'tEstE
union
select 'TESTE'

SELECT *
from tbl_teste

select distinct(nome)
from tbl_teste

select distinct(UPPER(nome))
from tbl_teste

select distinct(nome) COLLATE sql_latin1_general_cp1_ci_ai
from tbl_teste

Existem outras formas de solucionar isso,,, trocar o collation da coluna direto na tabela, criar uma view, etc etc…