quarta-feira, 19 de novembro de 2008

Desinstalando o SQL 2005 Embedded edition

O SQL Embedded edition n�o exp�e uma maneira simples de se desinstalar sua inst�ncia.

Recentemente tive que fazer isso quando fui configurar o WSS em uma m?quina que ja tinha uma inst�ncia do SQL Embedded e esta inst�ncia estava com problemas. Ou seja, eu precisava desinstalar a inst�ncia problem�tica antes de proceder com a instala��o do WSS.

Aqui vai o caminho das pedras para se desinstalar o SQL Embedded:

Abra o editor de registro do Windows (v� ao Iniciar > Executar e digite regedit) e localize a seguinte chave de registro:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

No painel esquerdo, clique em cada um dos GUIDs que est?o listados. Para cada GUID que voc? selecionar, procure na parte direita do Editor de registro pelo nome "Microsoft SQL 2005 Embedded Edition".

Quando voc� encontrar, copie o valor da chave "UninstallString", execute o prompt de comando (iniciar> executar > cmd), clique com o bot�o direito e cole o texto copiado da chave. Complemente o comando com "CALLERID=OCSETUP.EXE".
Ex.: "MsiExec.exe /X{BDD79957-5801-4A2D-B09E-852E7FA64D01} CALLERID=OCSETUP.EXE"

Basta executar o comando.

Ap�s a desinstala��o, reinicie a m�quina.

At� a pr�xima

terça-feira, 15 de julho de 2008

Removendo Registros Duplicados

Segue um procedimento simples, fácil e comentado para remoção de resgistros duplicados de uma tabela.Basta você adaptá-lo ao seu caso, escolhendo qual o critério de duplicação. No exemplo estamos usando os campos ID, NOME E SALARIO. Script para criaçao de uma tabela fictícia, para então podermos realizar nossos testes:

CREATE TABLE [dbo].[Funcionarios] (
[id] [int] NULL ,
[nome] [Varchar] (50) NULL,
[salario] [Numeric](18, 2) NULL
) ON [PRIMARY]

GO

-- populando a tabela com registros duplicados
Insert into Funcionarios values (1,'Rambo', 1000.00)
Insert into Funcionarios values (1,'Rambo', 1000.00)
Insert into Funcionarios values (2,'Joelson', 1000.00)
Insert into Funcionarios values (2,'Joelson', 1000.00)
Insert into Funcionarios values (3,'Blue Mary', 1000.00)
Insert into Funcionarios values (4,'Mary Julie', 5000.00)
Insert into Funcionarios values (2,'Joelson', 1000.00)
Insert into Funcionarios values (1,'Rambo', 1000.00)

-- Verificando os registros duplicados
SELECT * FROM [dbo].[Funcionarios] ORDER BY nome

Agora basta executar o procedimento de exclusão de registros duplicados.


DECLARE @DupCount INT
SET @DupCount = 0

-- Conta os itens duplicados
SELECT
@DupCount = COUNT(*)
FROM
Funcionarios
GROUP BY id, nome, salario
HAVING COUNT(*) > 1

-- Executa um WHILE onde iremos excluir cada um dos registros duplicados
WHILE @DupCount > 0
BEGIN
SET ROWCOUNT 1

-- Exclui as duplicações de acordo com os critérios do filtro (ID, nome e salario)
DELETE Funcionarios
FROM Funcionarios
JOIN (
SELECT id, nome, salario
FROM Funcionarios
GROUP BY id, nome, salario
HAVING COUNT(*) > 1
) Funcionarios_ALIAS
ON Funcionarios.id = Funcionarios_ALIAS.id
AND Funcionarios.nome = Funcionarios_ALIAS.nome
AND Funcionarios.salario = Funcionarios_ALIAS.salario

SET ROWCOUNT 0

-- Conto quantos registros duplicados ainda existem e atribuo o resultado ao contador
SELECT
@DupCount = COUNT(*)
FROM (SELECT *
FROM Funcionarios
GROUP BY id, nome, salario
HAVING COUNT(*) > 1
) TAB
END

Executamos um select para verificar o resultado da exclusão

SELECT * FROM [dbo].[Funcionarios] ORDER BY nome

É isso ai. Até a proxima.

domingo, 11 de maio de 2008

Impersonate infalível

Segue aqui uma dica de como executar um trecho de código sobre o contexto de outro usuário que não a própria aplicação.

A classe utiliza bibliotecas nativas do Windows para autenticar o e assim identificar o contexto do usuário que você vier definir como o "executor" do trecho de código que precisa ser "impersonado".

Exemplo de usoi da classe "Impersonator":


using (new Impersonator( "admin", "dominio", "minha_senha123" ))
{

Util.LogEntry("Quem passou por esse trecho de código foi o administrador");

//Segue executando outras operações sob o contexto do usuário "admin"

}

A classe implementa a interface IDisposable. Assim, podemos instanciar a classe usando a diretiva using e aninhar o código a ser "impersonado" nesse escopo. Como todos sabemos, assim que o código sai do escopo da diretiva using, o método Dipose é invocado atumaticamente.

Como vocês podem ver no código, o método Dispose está implementado de forma a devolver o contexto para o usuário default assim que for chamado.

Mas e se caso eu queira compilar essa classe e cedê-la a alguem que pretenda usá-la num código VB .NET? Em VB .NET não existe a diretiva "using".

Basta chamar o Método Dispose explicitamente ou o método "UndoImpersonation();".

Chega de conversa e vamos ao download do código.

É isso ai.

Abraço e até o próximo post

Referencias: A classe original foi desenvolvida por Uwe Keim e modificada por mim.

domingo, 27 de abril de 2008

SQL Server - Usando a função EXISTS

Em diversas situações nos vemos obrigados a usar uma função que verificar se um determinado registro existe antes de decidir o que será feito. Um exemplo típido e quando queremos determinar se vamos atualizar ou criar um registro. É ai que entra a função EXISTS.

  • Exemplo: 
    if EXISTS (select *
    from authors
    where au_id = '172-32-1176')
    Print 'O registro já existe - Executaremos um Update'
    ELSE
    Print 'O registro não existe - Vamos executar um Insert'

A função recebe um único parâmetro, que é uma instrução SQL. Se para a instrução SQL passada registros existirem, a função irá retornar TRUE, do contário, retornará FALSE.

A vantagem do uso do EXISTS é que assim que ele encontra o primeiro registro, o processo é interrompido, salvando então recursos do servidor SQL, embora se a pesquisa estiver sendo feita em cima de uma PRIMARY KEY, a diferença não seja muito grande entre um e outro. Entretanto, haverá um enorme ganho de performance se você estiver fazendo busca por qualquer outro campo não indexado.

Observer esses dois exemplos:

  • if exists (select *
    from authors
    where state = 'ca')
    Print 'Registro Existe'
    ELSE
    Print 'Registro não existe'

    if (select count(*)
    from authors
    where state = '172-32-1176') > 0
    Print 'Registro existe'
    ELSE
    Print 'Registro não existe'

Examinando os bancos default do MS-SQL SERVER, na database "pubs", tabela "authors" existem somente 23 registros. Mesmo com tão poucos registros, a query com o IF EXISTS é executada 4 vezes mais rápido do que um "select count". Isso porque a query pára a sua execução assim que o primeiro registro é encontrado. Já no segundo exemplo, todos os registros que atenderem a condição serão processados (retornados).

É isso ai :)

sexta-feira, 7 de março de 2008

Consultando objetos no SQL Server

As vezes nos deparamos com situações onde precisamos listar em nossa aplicação os objetos criados no SQL server e que estão sendo usados na aplicação.

A tabela sysobjects do SQL Server armazena um registro para cada objeto criado no banco.

Em outras palavras, ele possui um registro para cada constraint, functions, stored procedures, e etc, existente no banco.

Com isso, a tabela sysobject pode ser usada para se coletar informações a respeito do banco.
Ela possui um campo chamado xtype, como filtro para os tipos de objetos queremos trazer informações.

Podemos por exemplo listar todas as tabelas do banco (user tables) com a seguinte query:

select * from sysobjects where xtype='U'

Da mesma forma, podemos listar todas as procedures apenas alterando o filtro:
select * from sysobjects where xtype='P'
Abaixo segue a lista de valores possíveis para o xtype:
  • C = CHECK constraint
  • D = Default ou DEFAULT constraint
  • F = FOREIGN KEY constraint
  • L = Log
  • P = Stored procedure
  • PK = PRIMARY KEY constraint
  • RF = Replication filter stored procedure
  • S = System table
  • TR = Trigger
  • U = User table
  • UQ = UNIQUE constraint
  • V = View
  • X = Extended stored procedure
Até a próxima

segunda-feira, 18 de fevereiro de 2008

Algumas funções úteis em JavaScript

Algumas funções em Javascript que na verdade são atalhos para sintaxe de VB.

Pra quem ainda não está acostumado com linguagens derivadas do C, acaba sendo útil.

//Retorna uma quantidade específica de caracteres de uma string, contando da esquerda para a direita.
function Left(str, n){
if
(n <= 0)
{
return "";
}
else if (n > String(str).length)
{

return str;
}
else
{

return String(str).substring(0,n);
}
}

//Retorna uma quantidade específica de caracteres de uma string, contando da direita para a esquerda.
function Right(str, n){
if (n <= 0)

{
return "";
}
else if (n > String(str).length)
{
return str;

}
else

{
var iLen = String(str).length;
return String(str).substring(iLen, iLen - n);
}
}

//Remove os espaços no ínicio e no fim da string.
//Ex.: Trim(" Alisson "); retorna "Alisson".
function Trim(str)
{
return str.replace(/^\s+\s+$/g,"");
}


façam bom proveito :)

quarta-feira, 13 de fevereiro de 2008

Formatar Data com o Microsoft SQL Server

Já vi muita gente dizer que mexer com data é chato em qualquer linguagem de programação. Concordo com as pessoas que ouvi dizer isso. O legal é que com o tempo você vai se acostumando e logo a tarefa chata de lidar com formatação se torna algo comum. Seja pela experiência prática ou por macetes que a gente aprende.

O que vou descrever nesse post é um macete muito útil pra formatação de datas no SQL Server, já que este não dispõe de uma função nativa onde possamos formatar uma data sem ter que ficar decorando parâmetros númericos de conversão.

Se eu precisar usar converter uma data pro formato "YYYYMMDD", precisamos fazer o seguinte:

SELECT CONVERT(CHAR(8), GETDATE(), 112)

Não seria muito mais intuitivo se pudessemos fazer assim? :

SELECT CONVERT(VARCHAR, GETDATE(), 'YYYYMMDD')

É. Mas não funciona assim.

Com isso, descrobri uma UDF (user defined function) que facilita nossa vida.

A função é a seguinte:

CREATE FUNCTION dbo.FormatDateTime
(
@dt DATETIME,
@format VARCHAR(16)
)
RETURNS VARCHAR(64)
AS
BEGIN
DECLARE @dtVC VARCHAR(64)
SELECT @dtVC = CASE @format

WHEN 'LONGDATE' THEN

DATENAME(dw, @dt)
+ ',' + SPACE(1) + DATENAME(m, @dt)
+ SPACE(1) + CAST(DAY(@dt) AS VARCHAR(2))
+ ',' + SPACE(1) + CAST(YEAR(@dt) AS CHAR(4))

WHEN 'LONGDATEANDTIME' THEN

DATENAME(dw, @dt)
+ ',' + SPACE(1) + DATENAME(m, @dt)
+ SPACE(1) + CAST(DAY(@dt) AS VARCHAR(2))
+ ',' + SPACE(1) + CAST(YEAR(@dt) AS CHAR(4))
+ SPACE(1) + RIGHT(CONVERT(CHAR(20),
@dt - CONVERT(DATETIME, CONVERT(CHAR(8),
@dt, 112)), 22), 11)

WHEN 'SHORTDATE' THEN

LEFT(CONVERT(CHAR(19), @dt, 0), 11)

WHEN 'SHORTDATEANDTIME' THEN

REPLACE(REPLACE(CONVERT(CHAR(19), @dt, 0),
'AM', ' AM'), 'PM', ' PM')

WHEN 'UNIXTIMESTAMP' THEN

CAST(DATEDIFF(SECOND, '19700101', @dt)
AS VARCHAR(64))

WHEN 'YYYYMMDD' THEN

CONVERT(CHAR(8), @dt, 112)

WHEN 'YYYY-MM-DD' THEN

CONVERT(CHAR(10), @dt, 23)

WHEN 'YYMMDD' THEN

CONVERT(VARCHAR(8), @dt, 12)

WHEN 'YY-MM-DD' THEN

STUFF(STUFF(CONVERT(VARCHAR(8), @dt, 12),
5, 0, '-'), 3, 0, '-')

WHEN 'MMDDYY' THEN

REPLACE(CONVERT(CHAR(8), @dt, 10), '-', SPACE(0))

WHEN 'MM-DD-YY' THEN

CONVERT(CHAR(8), @dt, 10)

WHEN 'MM/DD/YY' THEN

CONVERT(CHAR(8), @dt, 1)

WHEN 'MM/DD/YYYY' THEN

CONVERT(CHAR(10), @dt, 101)

WHEN 'DDMMYY' THEN

REPLACE(CONVERT(CHAR(8), @dt, 3), '/', SPACE(0))

WHEN 'DD-MM-YY' THEN

REPLACE(CONVERT(CHAR(8), @dt, 3), '/', '-')

WHEN 'DD/MM/YY' THEN

CONVERT(CHAR(8), @dt, 3)

WHEN 'DD/MM/YYYY' THEN

CONVERT(CHAR(10), @dt, 103)

WHEN 'HH:MM:SS 24' THEN

CONVERT(CHAR(8), @dt, 8)

WHEN 'HH:MM 24' THEN

LEFT(CONVERT(VARCHAR(8), @dt, 8), 5)

WHEN 'HH:MM:SS 12' THEN

LTRIM(RIGHT(CONVERT(VARCHAR(20), @dt, 22), 11))

WHEN 'HH:MM 12' THEN

LTRIM(SUBSTRING(CONVERT(
VARCHAR(20), @dt, 22), 10, 5)
+ RIGHT(CONVERT(VARCHAR(20), @dt, 22), 3))

ELSE

'Invalid format specified'

END
RETURN @dtVC
END
GO

Basta executar o código acima no console do seu SQL. Se você utiliza SQL 7 ou inferior, não tem problema, crie uma StoredProcedure e devolva o resultado num parâmetro de Output.

Para testar a função e todas as suas possibilidades, utilize o seguinte:

DECLARE @now DATETIME
SET @now = GETDATE()

PRINT dbo.FormatDateTime(@now, 'LONGDATE')
PRINT dbo.FormatDateTime(@now, 'LONGDATEANDTIME')
PRINT dbo.FormatDateTime(@now, 'SHORTDATE')
PRINT dbo.FormatDateTime(@now, 'SHORTDATEANDTIME')
PRINT dbo.FormatDateTime(@now, 'UNIXTIMESTAMP')
PRINT dbo.FormatDateTime(@now, 'YYYYMMDD')
PRINT dbo.FormatDateTime(@now, 'YYYY-MM-DD')
PRINT dbo.FormatDateTime(@now, 'YYMMDD')
PRINT dbo.FormatDateTime(@now, 'YY-MM-DD')
PRINT dbo.FormatDateTime(@now, 'MMDDYY')
PRINT dbo.FormatDateTime(@now, 'MM-DD-YY')
PRINT dbo.FormatDateTime(@now, 'MM/DD/YY')
PRINT dbo.FormatDateTime(@now, 'MM/DD/YYYY')
PRINT dbo.FormatDateTime(@now, 'DDMMYY')
PRINT dbo.FormatDateTime(@now, 'DD-MM-YY')
PRINT dbo.FormatDateTime(@now, 'DD/MM/YY')
PRINT dbo.FormatDateTime(@now, 'DD/MM/YYYY')
PRINT dbo.FormatDateTime(@now, 'HH:MM:SS 24')
PRINT dbo.FormatDateTime(@now, 'HH:MM 24')
PRINT dbo.FormatDateTime(@now, 'HH:MM:SS 12')
PRINT dbo.FormatDateTime(@now, 'HH:MM 12')

Pronto. Agora ficou até parecendo VB. Se lembram do FormatDateTime? :)

Minha sugestão é que vocês guardem num cantinho ai essa função pra que sempre que forem inicar um projeto novo, a tenham de fácil acesso, pois ela é bastante útil e poupa um bucado de tempo quando o assunto é formatar data no SQL Server.

Grande abraço.

Referência: www.aspfaq.com