Varchar sem tamanho definido

sexta-feira, 30 de outubro de 2009

Responda rápido, qual o resultado deste SELECT:

DECLARE @teste varchar(40)
SET @teste = '1111111111222222222233333333334444444444'
go
SELECT CONVERT(varchar, @teste)
-- OU
SELECT CAST(@teste as varchar)

Se você respondeu '1' ou '1111111111222222222233333333334444444444', errou.

Quando não se informa o tamanho do datatype de uma variável do tipo varchar, o padrão é sempre 30. Ou seja, a resposta correta é '111111111122222222223333333333'.

Então, ao criar uma tabela não se especificar o tamanho campo de tipo varchar, seria 30 também? Este INSERT seria possível?

CREATE TABLE #teste (campo varchar)
INSERT INTO #teste VALUES ('111111111122222222223333333333')

Erro:
String or binary data would be truncated.
The statement has been terminated.

Não, quando não se especifica tamanho de uma coluna do tipo varchar, o tamanho default é 1. Portanto:


CREATE TABLE #teste (campo varchar)
GO

INSERT INTO #teste VALUES ('1');

SELECT * FROM #teste

campo
-----
1

(1 row(s) affected)


Referência: http://msdn.microsoft.com/en-us/library/ms176089%28SQL.90%29.aspx


Para finalizar, apenas como curiosidade, é possível criar uma variável ou campo em uma tabela informando um sinônimo de tipo de dados. Exemplos:

DECLARE @nome character varying(20)
SET @nome = 'Renata'
SELECT @nome

-- e ainda

CREATE TABLE #teste (
id integer,
nome character varying(40),
salario double precision
)
GO

INSERT INTO #teste (id, nome, salario) VALUES (1,'Maria', 5230.5)
GO


Neste exemplo, ao invés de int, foi colocado integer. No lugar de varchar, character varying. E no lugar de float, foi colocado double precision.

Ao verificar a estrutura da tabela criada, ela foi criada conforme o tipo de dados de sistema do SQL Server.

USE tempdb
go

SP_HELP #teste

Resultado:



Column_name Type Computed Length Prec Scale Nullable TrimTrailingBlanks FixedLenNullInSource Collation
--------------- ------------------- ----------- ------- ------- ------- ----------- ------------------- ----------------------- -----------------------------
id int no 4 10 0 yes (n/a) (n/a) NULL
nome varchar no 40 yes no yes SQL_Latin1_General_CP1_CI_AS
salario float no 8 53 NULL yes (n/a) (n/a) NULL

A lista completa de sinônimos se encontra aqui: http://msdn.microsoft.com/en-usprecision/library/ms177566%28SQL.90%29.aspxstyle

Separação de Lotes com o comando "GO"

quarta-feira, 28 de outubro de 2009

Esta semana me perguntaram: "Renata, para que serve o comando 'GO' ao final de uma query?". Titubiei e não consegui responder. Apenas disse: "É uma forma de comitar instruções que modificam estrutura do banco. Semelhante ao Commit que escreve o registro no arquivo de dados".

Diante dessa resposta mal dada, resolvi procurar pelo site do MSDN.

Sintaxe:
GO [count]
Sinaliza o término de um lote de instruções Transact-SQL para os utilitários SQL Server. O count define quantas vezes o lote acima do 'GO' deve ser executado.

Num exemplo, se executo uma query para criação de uma View e antes existe alguma outra instrução como um 'USE [Banco]', sei que a solução é colocar um 'GO' antes do 'Create View':

Tentativa 1 - Um único lote para escolha do banco de dados, criação da view e select na view

Comando:



USE B_BANCO

CREATE VIEW V_VIEW AS SELECT * FROM T_TABELA

SELECT * FROM V_VIEW


Resultado:
Msg 111, Level 15, State 1, Line 3
'CREATE VIEW' must be the first statement in a query batch.


Tentativa 2 - Adicionei ';' para tentar separar os comando

Comando:


USE B_BANCO;

CREATE VIEW V_VIEW AS SELECT * FROM T_TABELA;

SELECT * FROM V_VIEW;


Resultado:
Msg 111, Level 15, State 1, Line 3
'CREATE VIEW' must be the first statement in a query batch.


Tentativa 3 - Inclusão do comando 'GO' para separar a query em dois lotes

Comando:


USE B_BANCO;
GO


CREATE VIEW V_VIEW AS SELECT * FROM T_TABELA;

SELECT * FROM V_VIEW;


Resultado:
Msg 170, Level 15, State 1, Procedure V_VIEW, Line 2
Line 2: Incorrect syntax near ';'.


Tentativa 4 - Já conectada em B_BANCO, retirei o ';' e incluí 'GO' após o create view, criando assim três lotes

Comando:


USE B_BANCO;
GO

CREATE VIEW V_VIEW AS SELECT * FROM T_TABELA;
GO


SELECT * FROM V_VIEW;


Resultado:


SQ_DET_CLD PC_VR
----------- ---------------------------------------
1 2.00
2 2.00
4 2.00
5 2.00
6 2.00
8 43.00
9 2.00

(7 row(s) affected)



Explicação:

- Na tentativa 1, temos três instruções relacionadas e dependentes, por este motivo se encontram na mesma query. Porém, segundo o MSDN, Para CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER e CREATE VIEW não se pode combiná-los com outras instruções em um mesmo lote.

- Na tentativa 2, temos as mesmas instruções separadas por ponto e vírgula que é uma convenção usada na linguagem SQL que em Transact-SQL não é obrigatória, porém também não é errada. Mas em alguns comandos próprios da T-SQL não podem ser usados.

- Na tentativa 3, usando 'GO' depois do comando 'USE', o bloco de código foi separado entre dois lotes. Desta forma, o banco B_BANCO foi posicionado, porém a view não foi criada por haver ";" ao final do comando Create View.

- Já na tentativa 4, a retirada do ';' e a inclusão do 'GO' ao final do comando 'Create View', separou a transação em três lotes possibilitando a criação da view e exibição do resultado pelo comando Select ao final.

Apenas por curiosidade, tentei uma quinta tentativa:


Tentativa 5 - Retirada do 'GO' após o 'USE'

Comando:


USE B_BANCO

CREATE VIEW V_VIEW AS SELECT * FROM T_TABELA
GO

SELECT * FROM V_VIEW


Resultado:
Msg 111, Level 15, State 1, Line 4
'CREATE VIEW' must be the first statement in a query batch.
Msg 208, Level 16, State 1, Line 1
Invalid object name 'V_VIEW'.

Explicação:
Foram retornadas duas mensagens de erro pois existe aí dois lotes. O primeiro lote retorna erro pois conforme falado, 'CREATE VIEW' deve ser a primeira instrução de um lote. O segundo lote, do 'Select', é compilado, mas por não existir a View ainda, retorna erro.

Sobre o uso de um número como argumento count de 'GO':
Comando:


USE B_BANCO
GO

CREATE TABLE T_TABELA (texto char(5))
GO

INSERT INTO T_TABELA VALUES ('teste')
GO 4

SELECT * FROM T_TABELA




Resultado:


Beginning execution loop

(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)

Batch execution completed 4 times.
texto
-----------
teste
teste
teste
teste

(4 row(s) affected)



Referência: http://msdn.microsoft.com/pt-br/library/ms175502.aspx

Mais uma pro caderninho!

Conflito em Collation

segunda-feira, 19 de outubro de 2009

Olá! Hoje vou falar sobre Collation. Ou Agrupamento, que é responsável por definir o tipo de codificação para o conjunto de caracteres de um banco de dados, tabela ou coluna.

Obrigatoriamente, ao instalar uma instância do SQL Server (2000, 2005 ou 2008), é possível escolher a Collation a ser usada como padrão. Ao criar um banco de dados, se nada for definido/alterado, a Collation usada será a padrão escolhida para a instância. Mesmo caso para a criação de uma coluna em uma tabela, se nada for definido, a collation padrão é a do banco de dados.

Para explicar melhor, mostro um exemplo possível de diferentes Collations definidas:

  • SQL_Latin_General_CP850_CI_AS para uma instância;
  • Latin1_General_CI_AS para um database desta mesma instância;
  • SQL_Latin1_General_CP1_CI_AI para uma coluna de uma tabela deste mesmo banco de dados.

Bom, esta semana tive um problema onde através de dois bancos diferentes, uma consulta buscando dados em um Linked Server, buscava dados de uma tabela tA no banco de dados A e servidor A e os relacionava com os campos B1, B2, B3 da VIEW vB e servidor B. Sim, da View B.

Erro:
Cannot resolve collation conflict for equal to operation.

Localizei a tabela tB, representada na view vB, alterei a Collation das colunas envolvidas no select para a mesma Collation usada nas colunas A1, A2 e A3:



ALTER TABLE tB ALTER COLUMN B1 CHAR(10) COLLATE SQL_Latin1_General_CP1_CI_AI NOT NULL
GO
ALTER TABLE tB ALTER COLUMN B2 CHAR(10) COLLATE SQL_Latin1_General_CP1_CI_AI NOT NULL
GO
ALTER TABLE tB ALTER COLUMN B3 CHAR(10) COLLATE SQL_Latin1_General_CP1_CI_AI NULL
GO



Porém mesmo assim ao executar a query, o erro era o mesmo. Erro:
Cannot resolve collation conflict for equal to operation.

Percebi então que mesmo depois da alteração, nas propriedades daquela View, todas as colunas em sua estrutura ainda tinham a Collation antiga. Foi então que rodei o seguinte comando:



SP_REFRESHVIEW vB

GO



Executei novamente a query e já não havia mais conflito. \o/

Em resumo, se a alteração fosse feita no database, os objetos ali já criados permaneceriam com sua Collation anteriormente definida inalteradas. É necessário então modificar a Collation em tabela por tabela e ao final fazer Refresh nas Views.


Estes links ajudaram muito a solucionar este problema:

http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!183.entry

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=96516

Certificação MCTS Já!

sábado, 10 de outubro de 2009

Olá, já terminei os treinamentos 2778, 6231 e 6232. Agora é hora de escolher uma prova e focar nos estudos.

Escohi fazer primeiro a 70-432 - Microsoft SQL Server 2008, Implementation and Maintenance, pois é o meu objetivo principal e grande parte das atividades que desenvolvo.

Para começar, reuni todo material que tenho como pdf´s de livros, material oficial (antigamente chamado de MOC) e ainda dei uma passadinha na livraria Cultura e dei uma bela lida no primeiro capítulo do Training Kit 70-432. Ao final de cada lição dentre os capítulo, o livro apresenta algumas questões para fixar o entendimento.

Não comprei o livro, mas deveria, pois além do ótimo conteúdo, ele traz também um CD que possui um simulado. Como este gasto não estava nos plano, decidi tentar passar no exame apenas com estudo sobre o material adquirido e os conhecimentos fresquinhos na mente. Caso, não consiga, daí sim, compro o Training Kit e pago a segunda prova.

Bom, para ajudar nessa empreitada, terça-feira marcarei a prova e depois será a corrida contra o relógio para aproveitar todo o tempo livre e fixar o conhecimento.

Existe um outro caminho para passar em certificações, seria decorando as respostas do teste. Ocorre que algumas empresas vendem um software com o banco de dados das questões das provas de cada certificação Microsoft. Sinceramente, prefiro "gastar" dinheiro (e tempo) estudando nos livros e na prática. Se tiver que passar assim, prefiro reprovar quantas vezes forem necessárias. Acabo de me lembrar que isso pode ser de família, a coitada da minha avó, resolver tirar carteira de motorista aos 65 anos, reprovou 8 vezes e na 9 vez, ela conseguiu! :)

Vó Maria e sua permissão para dirigir


Achei um site bem bacana que mostra detalhadamente o conteúdo que deve ser estudado. Taí: http://ochoco.blogspot.com/2009/02/exam-70-432-ts-microsoft-sql-server.html

Pra finalizar, o valor do Training Kit é de R$148,00 na loja da livraria Cultura e de R$135,78 pela loja virtual. <Link Aqui>
Já o teste, deve ser marcado pelo site da Prometric e custa $80,00. <Link Aqui>

Como segunda-feira é feriado, será meu SQL Server day!
Até logo!

E se Chuck Norris fosse DBA?

sexta-feira, 9 de outubro de 2009

Sei que o intuito deste espaço é mostra visão feminina dentre as atividades corriqueiras de um(a) DBA, mas, para descontrair, vejamos como os bancos de dados se comportam quando Chuck Norris está à frente.

Pra quem não sabe, Roundhouse Kick, é um golpe mortal dentre as artes marciais. Sim, mortal quando se fala em Chuck Norris (http://pt.wikipedia.org/wiki/Chute_circular):



* Chuck Norris não faz DELETEs. Ele olha para os registros e eles correm de medo.
* Chuck Norris não cria Primary Keys. Os registros simplesmente não atrevem-se a duplicar.
* Chuck Norris não usa LOG. Ele lembra de todos registros que alterou.
* Chuck Norris não cria Índices. Ele sabe que os registros retornarão o mais rápido que puderem.
* MSSQL Server é muito mais rápido que Oracle. Basta que o DBA seja CHUCK NORRIS.
* Uma vez adaptaram o Roundhouse Kick para o Oracle. Assim nasceu o TRUNCATE TABLE.
* Chuck Norris não dá DROP TABLE. Ele dá ROUNDHOUSE KICK TABLE.
* Uma vez Chuck Norris deu um Roundhouse Kick em um banco poderoso. Hoje ele é conhecido por Access.
* Chuck Norris sabe todos os erros do Oracle de cor. Porque ele os criou.
* SELECT SUM(FORÇA) FROM CHUCK_NORRIS; Internal error. Do not call the support.
* SELECT CHUCK_NORRIS; Drop database sucessful.
* SELECT ROUNDHOUSE_KICK FROM CHUC... Lost connection.
* DELETE FROM CHUCK_NORRIS. Not Found. (Ele está atrás de você, a ponto de dar um Roundhouse Kick!!!)
* Chuck Norris tem IGNORE CONTRAINTS automático. Ninguém restringe nada a Chuck Norris. Ninguém.
* Chuck Norris não faz cursos de Oracle. A Oracle é que faz cursos de Chuck Norris.
* Chuck Norris instala o Oracle sem ler o manual. (Quem você pensa que é para ter tentado isso?)
* Chuck Norris instala o Oracle em um 486. Rodando Kurumim. Em 2 minutos.
* Chuck Norris instala o MSSQL Server em um Pentium 100MHZ. Rodando Solaris. A partis dos fontes.
* Chuck Norris instala o DB2 em um 486. Rodando Windows Vista. Sem HD.
* Chuck Norris não tem Certificação. São as empresas que tentam tirar Certificação em Chuck Norris. Em vão.
* Se disser ao DBA Chuck Norris que "o problema está no banco", é melhor que esteja se referindo ao Itaú.
* Chuck Norris SABE qual o problema de performance do banco. Ele só está dando uma chance do banco de se arrepender. 5... 4... 3...
* Chuck Norris não cria Stored Procedures. Todas suas Queries já se armazenam no banco, tentando se esconder. Mas é inútil.
* TRIGGERS tem este nome porque Chuck Norris sempre ameaçava atirar no banco quando ele não fazia algo automático.
* Chuck Noris não faz Modelo de Dados. Ele encara o banco até que ele faça o modelo sozinho.
* Chuck Norris instala o Oracle sem a interface gráfica. E sem a interface texto. (Pergunte a ele você!)
* Megabyte, Gigabyte, Terabyte, Petabyte, Exabyte, Chuckbite.
* Oracle tem as versões Personal, Standard, Enterprise e ChuckNorris Edition. Mas nenhum computador é rápido o suficiente para rodar a último.



Texto extraído de: http://www.simpatico.com.br/piada.exibir.php?tipoPiada=23&codPiada=126

Erro de conexão de Java para SQL Server 2000

sexta-feira, 2 de outubro de 2009

Os principais SGBDRs podem ser usados como banco de dados de vários tipos de aplicações. Como Java, .Net, PHP e etc...

Mas, é necessário ficar atento para a versão do banco de dados que de fato pode ser usado. Normalmente nas especificações do cliente, se obtém estes dados.

Quando o banco é fornecido pela mesma empresa da aplicação, as chances de compatibilidade são grandes (Como .Net e Sql Server, ou .Net e Access).

Num espaço de uma semana, me deparei com o mesmo problema duas vezes: Aplicação Java não conecta ao banco de dados SQL Server 2000.

Como o acesso via Enterprise Manager e Query Analyser era feito normalmente pelo programador, fiquei sem entender e disse: deve ser um problema de bibliotecas do java ou algo assim.

O próprio programador foi atrás dos requisitos de sua aplicação (Websphere) e me passou a solução: era necessário atualizar o Service Pack da instância do SQL 2000 utilizada que a conexão passaria a funcionar. Dito e feito!!! Baixei o SP4 do SQL Server 2000 em http://www.microsoft.com/Downloads/details.aspx?familyid=8E2DFC8D-C20E-4446-99A9-B7F0213F8BC5&displaylang=pt-br#Overview, extrai os arquivos num diretório e executei o utilitário de atualização.

As atualizações do SQL Server 2000 são:

SP4 - versão 8.00.2039
SP3 - versão 8.00.760
SP2 - versão 8.00.534
SP1 - versão 8.00.384
RTM - versão 8.00.194

Para verificar a versão do SQL de seu servidor, em qualquer versão do SQL, execute:

SELECT @@version:



Microsoft SQL Server 2000 - 8.00.760 (Intel X86)
Dec 17 2002 14:22:05
Copyright (c) 1988-2003 Microsoft Corporation
Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)


Para informações mais aprimoradas do servidor, como versão do Windows instalado e tipo de processador, execute:

EXEC master..xp_msver:


Index Name Internal_Value Character_Value
------ -------------------------------- -------------- ------------------------------------------------------------------------------------------------------------------------
1 ProductName NULL Microsoft SQL Server
2 ProductVersion 524288 8.00.760
3 Language 1033 English (United States)
4 Platform NULL NT INTEL X86
5 Comments NULL NT INTEL X86
6 CompanyName NULL Microsoft Corporation
7 FileDescription NULL SQL Server Windows NT
8 FileVersion NULL 2000.080.0760.00
9 InternalName NULL SQLSERVR
10 LegalCopyright NULL © 1988-2003 Microsoft Corp. All rights reserved.
11 LegalTrademarks NULL Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation
12 OriginalFilename NULL SQLSERVR.EXE
13 PrivateBuild NULL NULL
14 SpecialBuild 49807360 NULL
15 WindowsVersion 248381957 5.2 (3790)
16 ProcessorCount 1 1
17 ProcessorActiveMask 1 00000001
18 ProcessorType 586 PROCESSOR_INTEL_PENTIUM
19 PhysicalMemory 1023 1023 (1073164288)
20 Product ID NULL NULL



A lista completa de versões do SQL Sever e atualizações você encontra aqui:
http://www.sqlteam.com/article/sql-server-versions

O serviço do SQL não 'starta' depois da limpeza de disco (Disk Cleanup)

quinta-feira, 1 de outubro de 2009

Olá! vou relatar um problema que tive em um servidor de banco de dados ao executar a limpeza de disco.

Tenho uma máquina com uma instância SQL 2005 e outra SQL 2008 - ambas Enterprise. Como precisei liberar uso de memória e CPU, dei um stop em todos os serviços de SQL Server:



Por falta de espaço em disco, efeutei também a limpeza via Disk Cleanup:



Num dado momento, precisei startar o serviço do SQL 2005 que startou normalmente, mas o 2008 não.
Erro: Windows could not start the Sql Server (SQL2008) on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 3417.



Assim, após diversas buscas na web, e unindo infos de um post e outro, descobri que era necessário descomprimir os ldf´s e mdf´s do diretório DATA. Eles foram comprimidos no processo de limpeza de disco:






Pelo SQL Server Configuration Manager, startei normalmente o serviço. Poderia ser também pela ferramenta Services do Windows:



A maioria dos foruns relata comumente este erro no SQL Express 2005. Mas para 2008, não encontrei nada.

Prontinho, SQL 2008 de pé e pronto para uso. Let´s go!