FUNCOES SQL

19
FUNCOES SQL Funções de agrupamento: AVG() = Retorna o valor médio de uma coluna específica BINARY_CHECKSUM() = O valor do BINARY_CHECKSUM computado sobre uma linha ou uma tabela ou sobre uma lista de expressões. BINARY CHECKSUM é usada para detectar alterações em uma linha ou uma tabela. CHECKSUM() = O valor de CHECKSUM computado sobre uma linha ou uma tabela, ou sobre uma lista de expressões. CHECKSUM é usada para construir índices de hash. CHECKSUM_AGG() = O valor de CHECKSUM de um grupo. Valores nulos são ignorados. COUNT() = Retorna o número de linhas COUNT_BIG() = igual ao COUNT mas o COUNT_BIG sempre retorna um tipo de dados bigint. MAX() = Retorna o valor máximo de uma coluna específica MIN() = Retorna o valor mínimo de uma coluna específica SUM() = Retorna a soma de uma coluna específica STDEV() = Desvio padrão de todos os valores STDEVP() = Desvio padrão da população VAR() = Variância estatistica de todos os valores VARP() = Variância estatística de todos os valores da população Funções de manipulação de strings: ASCII(string) = pega o valor em ASCII da string CHAR(integer) = troca inteiro do ASCII em um caracter LEN(string) = Identifica o comprimento de uma expressão em caracteres LOWER(string) = converte uma string uppercase para lowercase. LTRIM(string) = remove os espaços em branco PATINDEX(posicao, expressao) = devolve a posicão de uma string dentro de um texto. Se não encontrar, retorna zero. REPLICATE(string, integer) = Repete N vezes um caractere especificado REVERSE(string) = retorna o inverso de uma expressao RTRIM (string) = remove os espaços em branco à direita de uma string SPACE(integer) = que retorna o número de espaços em branco informados no parâmetro STUFF(string texto, X, Y, string texto_a_inserir) = apaga da string "texto" os y caracteres a partir da posição x e os substitui por "texto_a_inserir" SUBSTRING(string texto, posicao_inicial, tamanho) = retorna uma string com o comprimento definido em "tamanho" extraida da string "texto", a partir da "posicao_inicial" UPPER(string) = retorna string em maiusculas Funções de manipulação de data/hora:

description

FUNCOES SQL

Transcript of FUNCOES SQL

FUNCOES SQL

Funções de agrupamento:

AVG() = Retorna o valor médio de uma coluna específicaBINARY_CHECKSUM() = O valor do BINARY_CHECKSUM computado sobre uma linha ou uma tabela ou sobre uma lista de expressões. BINARY CHECKSUM é usada para detectar alterações em uma linha ou uma tabela.CHECKSUM() = O valor de CHECKSUM computado sobre uma linha ou uma tabela, ou sobre uma lista de expressões. CHECKSUM é usada para construir índices de hash.CHECKSUM_AGG() = O valor de CHECKSUM de um grupo. Valores nulos são ignorados.COUNT() = Retorna o número de linhasCOUNT_BIG() = igual ao COUNT mas o COUNT_BIG sempre retorna um tipo de dados bigint.MAX() = Retorna o valor máximo de uma coluna específicaMIN() = Retorna o valor mínimo de uma coluna específicaSUM() = Retorna a soma de uma coluna específicaSTDEV() = Desvio padrão de todos os valoresSTDEVP() = Desvio padrão da populaçãoVAR() = Variância estatistica de todos os valoresVARP() = Variância estatística de todos os valores da população

Funções de manipulação de strings:

ASCII(string) = pega o valor em ASCII da stringCHAR(integer) = troca inteiro do ASCII em um caracterLEN(string) = Identifica o comprimento de uma expressão em caracteresLOWER(string) = converte uma string uppercase para lowercase.LTRIM(string) = remove os espaços em brancoPATINDEX(posicao, expressao) = devolve a posicão de uma string dentro de um texto. Se não encontrar, retorna zero.REPLICATE(string, integer) = Repete N vezes um caractere especificadoREVERSE(string) = retorna o inverso de uma expressaoRTRIM (string) = remove os espaços em branco à direita de uma stringSPACE(integer) = que retorna o número de espaços em branco informados no parâmetroSTUFF(string texto, X, Y, string texto_a_inserir) = apaga da string "texto" os y caracteres a partir da posição x e os substitui por "texto_a_inserir"SUBSTRING(string texto, posicao_inicial, tamanho) = retorna uma string com o comprimento definido em "tamanho" extraida da string "texto", a partir da "posicao_inicial"UPPER(string) = retorna string em maiusculas

Funções de manipulação de data/hora:

nomes das partes de data:

Year = yy, yyyyQuarter = qualquer, queMonth = mm, mDayofyear = dy, yDay = dd, dWeek = wk, wwHour = hhMinute = mi, nSecond = ss, sMillisecond = ms

DATEADD (parte, numero, data) = adiciona um valor a parte de uma dataDATEDIFF (parte, data inicial, data final) = subtrai a data inicial da data final, indicando o resultado na unidade definida em "parte"GETDATE() = retorna a data atual do sistemaDATENAME (parte, data) = retorna o nome da parte de uma dataDATEPART(parte, data) = retorna a parte de uma data

Funções de Sistema:

CAST(expressao as datatype) = converte uma expressao no datatype informadoCOL_LENGTH(nome_da_tabela, nome_da_coluna) = retorna o tamanho da colunaCOL_NAME(id_da_tabela, id_da_coluna) = retorna o nome da colunaDATALENGTH(expressao) = retorna o numero de bytes usados para armazenar a expressaoDB_ID(nome_do_banco) = retorna o ID do banco informadoDB_NAME(id_do_banco) = retorna o nome do bancoHOST_ID() = retorna a ID da estação que está acessando o SQL ServerHOST_NAME() = retorna o nome da estação que está acessando o SQL ServerIDENT_INCR(nome_da_tabela_ou_view) = retorna o valor incrementadoIDENT_SEED(tabela_ou_view) = retorna o valor inicial da colunaINDEX_COL(nome_da_tabela, indice_id, chave_id) = retorna o nome da coluna que participa do índiceISNULL(expressao, valor) = se a expressao for null, troca pelo valor especificadoISNUMERIC(expressao) = retorna 1 se a expressao for numerica e 0 se não forNEWID() = retorna um novo valor do tipo uniqueidentifierNULLIF(expressao_1, expressao_2) = retorna nulo se as duas expressoes forem equivalentes. Se não forem, retorna a primeira expressao.OBJECT_ID(nome_do_objeto) = retorna o ID de um objeto, a partir do nome fornecidoOBJECT_NAME(ID_do_objeto) = retorna o nome do objeto, a partir do ID fornecidoPARSENAME(objeto, parte) = retorna a parte do nome de um objeto, desde que tenha sido qualificadoSTATS_DATE(tabela_id, indice_id) = retorna a data em que as estatísticas do índice foram atualizadasSUSER_SID(nome_do_usuario) = retorna o ID do usuario informadoSUSER_NAME(usuario_id) = retorna o id do usuário no servidor. O argumento é opcional.SUSER_SNAME(id_do_usuario) = retorna o nome do usuario informado. Se nenhum ID de usuario for passado para a função, retorna o nome do usuario logadoUSER_ID(nome_do_usuario) = retorna o ID do usuario informado para o BD em usoUSER_NAME(id_do_usuario) = retorna o usuario conectado ao BD

Funções Matematicas:

ABS(numero) = retorna o valor absoluto do numeroACOS(float) = retorna o arco-coseno do numero informadoASIN(float) = retorna o arco-seno do numero informadoATAN(float) = retorna o arco-tangente do numero informadoATN2(Float expressao_1, float expressao_2) = Arco-tangente do valor definido pela divisão da primeira expressão pela segundaCEILING(numero) = retorna o menor inteiro que seja maior ou igual ao numero informadoCOS(float) = retorna o coseno do numero informadoCOT(float) = retorna o cotangente do numero informadoDEGREES(numero) = converte radianos para grausEXP(float) = retorna o exponencial de um numero especificadoFLOOR(numero) = retorna o maior inteiro que seja menor ou igual ao numero informadoLOG(float) = retorna o logaritmo natural do numero informadoLOG10(float) = retorna o logaritmo base 10 do numero informadoPI() = retorna o valor de PI 3.1415926535897931.POWER(numero, potencia) = retorna o valor elevado à potencia informadaRADIANS(numero) = converte graus para radianos

RAND(expressao) = um número aleatório entre 0 e 1. Expressão é opcional e será usada como semente da cadeia pseudo-aleatóriaROUND(numero, precisao, arredonda_ou_trancar) = arredonda ou tranca o numero fornecido de acordo com a precisao informada. Se o terceiro parametro não for passado para a funçao, o numero é arredondado. Se quiser que o numero seja truncado, deve-se fornecer o valor 1SIGN(numero) = retorna sinal positivo, negativo ou zero do numeroSIN(float) = retorna o seno do angulo especificadoSQRT(float) = retorna a raiz quadrada de um numeroTAN(float) = retorna a tangente de um numero informadoSQUARE(float) = retorna o quadrado de um numero

Função de conversão:

CONVERT(tipo(tamanho), expressão, estilo) = converte a expressão para o tipo de dado. O tamanho e o estilo são opcionais

No atual post prentende-se discutir/exemplificar alguns pontos que poderão serem úteis tanto no entendimento/clareza quanto na performance das queries e stored procedure. Não são regras, são apenas "dicas" cada caso é um caso. Utilize-as sempre que possível, lembrando que alguns casos poderemos perder em performance para atender determinadas situações.

Esta dicas podem ser aplicadas em quase todos os bancos de dados que utilizem padrão ANSI.

1. Uso do Select *Sempre que possível evitar o uso de select * mesmo que a Stored Procedure retorne todos as colunas de uma tabela. Com isso, garante-se a segurança e manutenabilidade da SP, pois sabe-se exatamente quais parâmetros ela retorna assim que se visualiza o seu código.

2. Uso de > ou >=Situação: A query é:

CODE

select c1,c2 from t where a > 3

e a tabela possui índice em a..

Se houver muitas linhas com a = 3, o engine do banco de dados fará scan de muitas páginas até encontrar a > 3.

É mais eficiente se escrita da forma:

CODE

select c1,c2 from t where a >= 4

3. Exists ou Not ExistsDe maneira geral o uso de EXISTS e IN é mais eficiente que NOT EXISTS e NOT IN.

Situação:

CODE

if not exists ( select a from t where a = 3 )begin .....grupo 1endelsebegin .....grupo 2end

É mais eficiente se escrita da forma

CODE

if exists ( select a from t where a =3 )begin ... grupo 2end elsebegin ... grupo 1end

No SELECT de um EXISTS tomar cuidado para não colocar * ou colunas que não sejam índice cluster, pois o EXISTS não necessita retornar colunas somente verificar se a linha existe ou não. Assim, utilizar if exists:

CODE

select 1 from t where a > 3

ao invés de if exists:

CODE

( select * from t where a > 3)

4. Subqueries com cláusula de outer-join restritiva

CODE

select w from outer where y = 1 and x = (select sum(a) from inner where inner.b = outer.z )

Será quebrada pelo bancod e dados nos seguintes passos

CODE

select outer.z, summ = sum(inner.a)into #work from outer, innerwhere inner.b = outer.z and outer.y = 1group by outer.z

select outer.wfrom outer, #workwhere outer.z = #work.z and outer.y = 1 and outer.x = #work.summ

O bancod de dados copia a cláusula search ( y = 1 ) para a subquery, mas não copia cláusula join. Isto porque copiando a cláusula search, sempre tornará a query mais eficiente, mas copiando a cláusula join pode em muitos casos tornar a query mais lenta. A cópia da cláusula join só é eficiente quando ela é extremamente restritiva, mas o banco de dados faz a quebra antes do otimizador atuar. Então, para tornar a query mais eficiente, conhecendo previamente a alta restritividade da cláusula join, pode-se copiar a cláusula join para a subquery como no exemplo abaixo :

tab_x -> tabela grandetab_y -> tabela pequena

CODE

select a from tab_x, tab_ywhere tab_x.coluna_valor_unico = tab_y.a and tab_x.b = ( select sum© from tabela_interna where tab_x.d = tabela_interna.e and tab_x.coluna_valor_unico = tab_y.a)

5. Criação de tabelas dentro de stored proceduresQuando uma tabela é criada e utilizada dentro de uma mesma stored procedure, o otimizador não tem conhecimento das suas estatísticas, e assume que esta tabela tem 100 linhas e 10 páginas. Se a tabela criada é muito grande, esta suposição pode levar o otimizador a calcular um plano de acesso não otimizado. Para evitar este problema, crie a tabela em uma procedure e utilize-a em outra. Isto será objeto de especificação durante o Diagrama de Cenários.

6. Variáveis ou parâmetros na cláusula whereO otimizador não tem informações sobre o valor de uma variável, mas, em tempo de compilação, sabe o valor de um parâmetro. Isso posto, a utilização de parâmetros em cláusula where, leva o otimizador a produzir um plano de acesso mais eficiente.

Por exemplo, a procedure

CODE

create procedure s_p1 as declare @x intselect @x = b1 from t where a1 = 3select a from t2 where b1 = @x

pode ser reescrita como :

create procedure s_p1 as declare @x intselect @x = b1 from t where a1 = 3exec s_p2 @x

create s_p2 @x int as select a from t2 where b1 = @x

7. COUNT x EXISTSPara testes de existência é sempre mais eficiente utilizar EXISTS do que COUNT. Quando se utiliza o COUNT o banco de dados não sabe que se está fazendo um teste de existência e continua pesquisando todas as linhas qualificadas. Já utilizando EXISTS, o banco de dados sabe que é um teste de existência e interrompe a pesquisa quando encontra a primeira linha qualificada.

Este mesmo raciocínio é válido quando se utiliza COUNT no lugar de IN ou ANY.

8. OR x UNIONO banco de dados não consegue otimizar cláusulas de join ligadas por OR. Neste caso é mais eficiente ligar os conjuntos de resultados por UNION.

Por exemplo :

CODE

select a from tab1,tab2 where tab1.a = tab2.a OR tab1.x = tab2.x

pode ser reescrito como :

CODE

select a from tab1, tab2where tab1.a = tab2.aUNIONselect a from tab1, tab2where tab1.x = tab2.x

A diferença é que na segunda forma, são eliminadas as linhas duplicadas, o que pode ser contornado com UNION ALL.

9. MAX e MIN AgregadosO banco de dados utiliza uma otimização especial para MAX e MIN quando há um índice na coluna agregada. Para o MIN a pesquisa é interrompida quando encontra a primeira linha qualificada.Para o MAX, o banco de dados vai diretamente para o final do índice e pega a última linha.

Os casos onde estas otimizações especiais não são utilizadas:

- a expressão do MAX ou MIN não é uma coluna.- a coluna do MAX ou MIN não é a primeira do índice- existe outro comando agregado na query.- existe uma cláusula de GROUP BY.- se existe cláusula WHERE, a otimização especial de MAX não é utilizada.

Se houver possibilidade de se conseguir otimização especial, vale a pena separar em várias queries. É mais eficiente utilizar o índice várias vêzes, do que fazer scan table uma única vez.

Em alguns casos, pode ser mais eficiente não utilizar a otimização especial do MIN. Por exemplo, se há uma cláusula where em outro índice, quanto mais restritivo for o WHERE, menos eficiente fica a otimização especial do MIN. A solução é convencer o otimizador a não utilizar a otimização especial

do MIN, colocando, por exemplo, duas agregações na query.

Por exemplo :

CODE

select MIN(coluna1)from tab where coluna2 =

O banco de dados utilizará aqui a otimização especial do MIN, e fará um scan em quase todo o índice, pois a qualificação na cláusula WHERE força esta situação. Se colocarmos mais um aggregate, convenceremos o otimizador a utilizar o processo normal, criando um plano de acesso pelo índice da coluna2, neste caso, mais eficiente que a otimização especial do MIN.

CODE

select MIN(coluna1), MAX[coluna2)from tab where coluna2 =

10. Joins e DatatypesSe a cláusula join utiliza datatypes diferentes, um deles será convertido para o outro. O datatype convertido é o hierarquicamente inferior. O otimizador não consegue escolher um índice na coluna que é convertida.

O ideal é evitar este tipo de join, mas se não for possível, pode-se explicitamente converter o lado do join que tem o menor custo de não utilização do índice.

Por exemplo :

CODE

select c1,c2 from tab1, tab2where tab1.col_char_75 = convert ( char(75), tab2.col_varchar_75 )

11. Parâmetros e DatatypesO otimizador pode utilizar o valor de um parâmetro para calcular o custo de um plano. Mas o banco de dados não poderá utilizar valores de parâmetros convertidos. O ideal então é garantir que o parâmetro tem o mesmo datatype da coluna com a qual ele será comparado.

Por exemplo :

CODE

create procedure s_p @x varchar(30) as select c1,c2 from tab where coluna_char_30 = @x

pode ser reescrito como:

CODE

create procedure s_p @x char(30) as select c1,c2 from tab where coluna_char_30 = @x

12. Testar retorno de comando SQL Após um comando SQL (select, insert, update, delete) sempre é necessário testar duas variáveis para um correto processamento da Stored Procedure: @@error (código de retorno do banco de dados ) e @@rowcount (quantidade de linhas retornadas pelo comando). Estas variáveis devem ser testadas para que a SP possa dar como retorno os códigos de erro -1001 (erro banco de dados ) e -1002 (não encontrou registro). No caso do raiserror, retornar 40001 e 40002 respectivamente.

Para testar siga o exemplo:

CODE

declare @erro smallint,@numlin smallint

select a from t where a > 3

/* sempre salvar o valor de @@error em uma variável pois para cada comando SQL o banco de dados gera um @@error. */

select @erro = @@error @numlin = @@rowcount

if @erro != 0return -1001 /* erro banco de dados */

if @numlin = 0return -1002 /* não encontrou registro */

13. Stored Procedure chamadoraPara as SP´s consideradas chamadoras, ou seja, aquelas que chamam outras SP´s deve-se tomar um cuidado especial com os códigos de retorno (vide quadro de códigos). Além dos códigos padronizados (0, -1001, -1002, ...) a SP ainda pode retornar códigos próprios dela durante a execução (códigos -1 a -14). Estes códigos sinalizam que houve algum tipo de problema para a execução da SP: não achou a SP, não existe permissão para executá-la, entre outras. Testar na SP chamadora estes códigos de retorno também.

Exemplo:

CODE

create procedure s_testeas declare @return int /* p/ código de retorno */

/* executa s_teste2 buscando seu código de retorno */

execute @return = s_teste2

/* testa retorno de s_teste2 */

if @return != 0begin raiserror 40001return -1001 /* erro banco de dados */end elsebegin raiserror 40000return 0 /* OK */ end

14. Utilização do comando RAISERRORO uso do RAISERROR no código é obrigatório para as SP´s chamadoras ou que retornem múltiplas todos´s da mesma tabela ou de tabelas diferentes. Isto faz-se necessário para facilitar e viabilizar o controle de erros nas aplicações PowerBuilder. O RAISERROR deve ser colocado antes de todos os return´s do código da SP. Ver padronização dos códigos no quadro CÓDIGOS DE RETORNO. Nas demais SP´s fica a critério do coordenador de cada equipe de desenvolvimento, a decisão pela obrigatoriedade da utilização do RAISERROR.

Exemplo: vide código SP do item acima.

15. Uso de campos formato DATA (smalldatetime e datetime)Tomar bastante cuidado com a utilização de campos no formato DATA, principalmente para utilização de datas zeradas e datas com 99999999. No banco de dados este conceito perdeu o sentido pois só são aceitas datas válidas para um campo formato DATA.

Assim, utilizar

1900/01/01 para representar DATA = 0

e

2070/12/31 para representar DATA = 99999999.

Estas datas são os limites abaixo e acima para os campos smalldatetime. Para casos aonde este range não seja suficiente, buscar orientação com o Suporte/Adm. de Dados.

Neste tópico vamos aprender como manipular Data (DATETIME ou SMALLDATETIME) no SQL Server.Não é um texto dogmático nem com pretensão de esgotar o assunto. As dicas e exemplos postados aqui representam o meu aprendizado diário. Funcionam! Porém não são verdades absolutas.

1. Sempre criar campos data com o formato DATETIME ou SMALLDATETIME. A diferença entre os dois tipos podem ser detalhadas nos Books Online. O exemplo a seguir mostra de forma simplificada como cada tipo atua:

CODE

----Retorna Data do sistema completa: AAAA-MM-DD 00:00:00.000

SELECT CAST(GETDATE() AS DATETIME)----Retorna Data do sistema completa (com arredondamento): AAAA-MM-DD 00:00:00SELECT CAST(GETDATE() AS SMALLDATETIME)---- Exemplos do Books Online-- --Retorna: 2000-05-08 12:35SELECT CAST('2000-05-08 12:35:29.998' AS SMALLDATETIME)SELECT CONVERT(SMALLDATETIME,'2000-05-08 12:35:29.998')----Retorna: 2000-05-08 12:36SELECT CAST('2000-05-08 12:35:29.999' AS SMALLDATETIME)SELECT CONVERT(SMALLDATETIME,'2000-05-08 12:35:29.999')--

OBS: Notem que tanto a função CAST como CONVERT retorna o mesmo resultado. Não existem impedimentos para se gravar uma data em um campo VARCHAR e depois utilizar CAST ou CONVERT para manipulá-lo. Porém como o tipo VARCHAR não impõe CONTRAINT para validar uma data, facilidade nativa dos tipos DATETIME/SMALLDATETIME, pode permitir a entrada de uma data inválida. Assim sendo se a aplicação por algum problema passar uma data invalida o banco de dados gravará a data inválida sem retornar erro algum. É claro que a aplicação realmente dever consistir e formatar a data a ser envia para o banco. Porém definindo a data no formato correto esta consistência será garantida a nível de banco de dados, além da aplicação.No post: http://forum.imasters.com.br/index.php?showtopic=223962 este assunto é tratado com um exemplo real.

2. Criando campos e variáveis do tipo data:

CODE

--Criando variáveis locais do tipo dataDECLARE @DT_INICIO DATETIMEDECLARE @DT_INICIO SMALLDATETIME

--Criando campos tipo data em tabelaCREATE TABLE #TMP (NU_COD INT, DT_INICIO DATETIME)CREATE TABLE #TMP (NU_COD INT, DT_INICIO SMALLDATETIME)

3. A forma como o banco de dados tratará/gravará/exibrá o campo data:

CODE

---- Exemplos do Books OnlineSET DATEFORMAT mdyDECLARE @datevar datetimeSET @datevar = '12/31/98'SELECT @datevar

SET DATEFORMAT ydmSET @datevar = '98/31/12'SELECT @datevar

SET DATEFORMAT ymd

SET @datevar = '98/12/31'SELECT @datevar

No post: http://forum.imasters.com.br/index.php?showtopic=223962 nosso companheiro eriva_br dá uma aula sobre o assunto. Vale uma conferida!

4. Inserindo registros em campos datas

CODE

CREATE TABLE #ATIVIDADES (DESCRICAO_ATIVIDADE VARCHAR(30),DT_INI DATETIME, DT_FIM DATETIME)

--Inserindo DT_INI no formato DD/MM/AAAA com a hora --e DT_FIM no formato DD/MM/AAAA sem a hora INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Requisitos','01/01/2005 00:00:00','01/01/2006')

--Inserindo DT_INI no formato AAAA/MM/DD sem a hora --e DT_FIM no formato DD/MM/AAAA sem a hora INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Modelagem','2006/01/02 ','05/07/2006')

--Inserindo DT_INI no formato AAAA/DD/MM com a hora --e DT_FIM no formato AAAA/DD/MM com a hora INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Implementação','2006/07/06 00:00:00','2007/04/25 00:00:00')

Como pode ser visto as datas podem ser inseridas de várias formas com hora ou não. Caso a hora não seja informada será usada 00:00:00 como padrão. Aqui onde trabalhamos normalmente enviamos a data para o SQL no formato AAAA/MM/DD pois neste formato grava-se a data em qualquer banco de dados ANSI.

5. Converter, mascarar, recuperar informações campos data:

Utilizando a função CONVERT pode-se retornar o conteúdo do campo data das seguintes formas:

CODE

SELECT CONVERT(VARCHAR(12),GETDATE(),101) AS '101',CONVERT(VARCHAR(12),GETDATE(),102) AS '102',CONVERT(VARCHAR(12),GETDATE(),103) AS '103',CONVERT(VARCHAR(12),GETDATE(),104) AS '104',CONVERT(VARCHAR(12),GETDATE(),105) AS '105',CONVERT(VARCHAR(12),GETDATE(),106) AS '106',CONVERT(VARCHAR(12),GETDATE(),107) AS '107',CONVERT(VARCHAR(12),GETDATE(),108) AS '108',CONVERT(VARCHAR(12),GETDATE(),109) AS '109',CONVERT(VARCHAR(12),GETDATE(),110) AS '110',CONVERT(VARCHAR(12),GETDATE(),111) AS '111',CONVERT(VARCHAR(12),GETDATE(),112) AS '112',CONVERT(VARCHAR(12),GETDATE(),113) AS '113',CONVERT(VARCHAR(12),GETDATE(),114) AS '114',CONVERT(VARCHAR(12),GETDATE(),120) AS '120',CONVERT(VARCHAR(12),GETDATE(),121) AS '121'

A função CONVERT além de devolver a data formatada, ou parte da mesma, permite efetuar a conversão do campo data para outros formatos. Nesta caso pode-se utilizar a funçao CAST para obter-se o mesmo resultado. Para concatenar um texto com uma data veja os exemplos:

CODE

SELECT CONVERT(VARCHAR(10),GETDATE(),103) + ' é a data de hoje'SELECT CAST(GETDATE() AS VARCHAR(10)) + ' é a data de hoje'

Normalmente utilizo o CONVERT e não o CAST, mas cada caso é um caso.Obs: Muita atenção no resultado da conversão de datas para outros formatos. As vezes não ocorre a concatenação e sim uma soma, principalmente na conversões para formato numérico.

6. Manipulando partes de data:

CODE

SELECT YEAR(GETDATE()) AS ANO,MONTH(GETDATE()) AS MES,DAY(GETDATE()) AS DIA----Utlizando DATEPART que retorna um INTEIRO contendo informações--sobre o campo dataSELECT DATEPART(YEAR, GETDATE()) AS ANO,DATEPART(MONTH, GETDATE()) AS MES,DATEPART(DAY, GETDATE()) AS DIA,

DATEPART(DAYOFYEAR, GETDATE()) AS DIA_ANO,DATEPART(WEEK, GETDATE()) AS SEMANA,DATEPART(HOUR, GETDATE()) AS HORA,DATEPART(MINUTE, GETDATE()) AS MINUTO----Utlizando DATENAME que retorna uma STRING(caracter) contendo informações--sobre o campo dataSELECT DATENAME (YEAR, GETDATE()) AS ANO,DATENAME (MONTH, GETDATE()) AS MES,DATENAME (DAY, GETDATE()) AS DIA,

DATENAME (DAYOFYEAR, GETDATE()) AS DIA_ANO,DATENAME (WEEK, GETDATE()) AS SEMANA,DATENAME (HOUR, GETDATE()) AS HORA,DATENAME (MINUTE, GETDATE()) AS MINUTO

Mais exemplos e particularidades de cada função pró-atividade e Books Online(procure por Date and Time Functions). :assobiando:

7. Datas e matemática. É possível? :devil:

CODE

----DATEDIFF retorna um INTEITO como resultado de operações--entre dua datasDECLARE @DT_EXEMPLO DATETIMESET @DT_EXEMPLO = '1966/01/01'

SELECT DATEDIFF(YEAR, @DT_EXEMPLO , GETDATE()) AS ANO,DATEDIFF(MONTH, @DT_EXEMPLO , GETDATE()) AS MES,DATEDIFF(DAY, @DT_EXEMPLO , GETDATE()) AS DIAS ----DATEADD retorna um DATETIME como resultado de adição entre datas--SELECT DATEADD(DAY, -10 , GETDATE()) AS DATA_ATUAL_MENOS_10_DIAS,DATEADD(DAY, 10 , GETDATE()) AS DATA_ATUAL_MAIS_10_DIAS,DATEADD(YEAR, -10 , GETDATE()) AS DATA_ATUAL_MENOS_10_ANOS,DATEADD(YEAR, 10 , GETDATE()) AS DATA_ATUAL_MAIS_10_ANOS

De novo, novamente! Mais exemplos e particularidades de cada função pró-atividade e Books Online(procure por Date and Time Functions). :assobiando:

8. O exemplo a seguir cria uma tabela temporária e executa vários select´s utilizando campos tipo data:

CODE

CREATE TABLE #ATIVIDADES (DESCRICAO_ATIVIDADE VARCHAR(30),DT_INI DATETIME, DT_FIM DATETIME)INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Requisitos','2005/01/01 00:00:00','2006/01/01 00:00:00') INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Modelagem','2006/01/02 00:00:00','2006/07/05 00:00:00') INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Implementação','2006/07/06 00:00:00','2007/04/25 00:00:00') INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Testes','2007/04/26 00:00:00','2007/06/20 00:00:00') INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Homoçogação','2007/06/21 00:00:00','2007/07/28 00:00:00') INSERT INTO #ATIVIDADES (DESCRICAO_ATIVIDADE,DT_INI,DT_FIM) VALUES ('Implantação','2007/07/28 00:00:00','2007/11/25 00:00:00')

---- Calculando a diferença entre a DT_INI e DT_FIM utilizando função DATADIFF--PRINT 'DT_FIM - DT_INI:'SELECT CONVERT(VARCHAR(10),DT_INI,103) AS DT_INI,CONVERT(VARCHAR(10),DT_FIM,103) AS DT_FIM,DATEDIFF(MONTH,DT_INI,DT_FIM) AS DIF_MES,DATEDIFF(DAY,DT_INI,DT_FIM) AS DIF_DIAS,DATEDIFF(WEEK,DT_INI,DT_FIM) AS DIF_SEMANA,DATEDIFF(HOUR,DT_INI,DT_FIM) AS DIF_HORA,DATEDIFF(MINUTE,DT_INI,DT_FIM) AS DIF_MINUTOSFROM #ATIVIDADES

---- Diminui 2 dias e soma 2 dias na DT_INI--PRINT 'SUBTRAI/SOMA DIAS EM DATA'SELECT CONVERT(VARCHAR(10),DT_INI,103) AS DT_INI,CONVERT(VARCHAR(10),DT_FIM,103) AS DT_FIM,CONVERT(VARCHAR(10),DATEADD(DAY,-2,DT_FIM),103) AS DOIS_DIAS_ANTES,CONVERT(VARCHAR(10),DATEADD(DAY,2,DT_FIM),103) AS DOIS_DIAS_DEPOIS

FROM #ATIVIDADES

----USANDO CASE NAS EXPRESSÕES:--PRINT 'Data Atual (GETDATE()) - DT_FIM: 'SELECT CONVERT(VARCHAR(10),DT_INI,103) AS DT_INI,CONVERT(VARCHAR(10),DT_FIM,103) AS DT_FIM,DATEDIFF(DAY,DT_INI,DT_FIM) AS 'DT_FIM-DT_INI',DATEDIFF(DAY,DT_INI,GETDATE()) AS 'GETDATE()-DT_INI',DATEDIFF(DAY,DT_FIM,GETDATE()) AS 'GETDATE()-DT_FIM',

CASEWHEN GETDATE() BETWEEN DT_INI AND DT_FIM THEN 'Iniciado'WHEN (DATEDIFF(DAY,DT_FIM,GETDATE())) < 1 THEN 'A iniciar'ELSE 'Finalizado'END AS DE_SITUACAO,

CASEWHEN (DATEDIFF(DAY,DT_FIM,GETDATE())) > 0 THEN '100 %'ELSE CASEWHEN CONVERT(VARCHAR(15),100 - ((100 * (DATEDIFF(DAY,DT_FIM,GETDATE()) * -1) ) / DATEDIFF(DAY,DT_INI,DT_FIM))) < 0 THEN '0 %'ELSE CONVERT(VARCHAR(15),100 - ((100 * (DATEDIFF(DAY,DT_FIM,GETDATE()) * -1) ) / DATEDIFF(DAY,DT_INI,DT_FIM))) + '%'ENDEND AS PERC_REAL

FROM #ATIVIDADES DROP TABLE #ATIVIDADES

Considerações:

Exemplo de WHERE dinâmico - sem utilização de EXEC ou CASE

A stored procedure a seguir efetua uma consulta em uma tabela de CLIENTES utilizando como critério oscampos: UF, CIDADE e BAIRRO.

A particularidade desta stored procedure é que ele é capaz efetuar a consulta de maneira dinâmica.

Ou seja a stored procedure receberá:

3 parâmetros EXEMPLO_WHERE_DINAMICO('UF','CIDADE','BAIRRO')

2 parâmetros EXEMPLO_WHERE_DINAMICO('UF','CIDADE')

1 parâmetro EXEMPLO_WHERE_DINAMICO('UF')

NENHUM parâmetro EXEMPLO_WHERE_DINAMICO()

E efetuará o filtro (WHERE) dinamicamente.

Segue código da stored procedure: