Arquivo
Série Mentes Brilhantes – Parte 15
O que fazer quando você não confia na clausula IF?
Simples, replique o código no ELSE IF.
Isso me lembra de uma frase que um amigo sempre fala: –“Se não vai no IF vai no ELSE.” (Brilhante)
DECLARE @Error Int,
@Message VarChar(200)
SET @Error = 1
IF @Error <> 0
BEGIN
SET @Message = dbo.ReturnError(‘InsertingError1’,@Error)
SELECT @Message AS Error
END
ELSE IF @Error <> 0
BEGIN
SELECT dbo.ReturnError(‘InsertingError1’,@Error) AS Error
END
Licenciamento Analysis Services
Outra pergunta que recebi de um cliente foi.
Posso instalar o SQL Server em uma máquina e o AS em outra? Como fica em relação ao licenciamento?
Infelizmente não pode, caso queira fazer isso terá que comprar outra licença do SQL para a máquina que irá rodar o AS. De fato, qualquer componente extra do SQL instalado em uma nova máquina, precisa de uma nova licença, seja AS, SSRS ou SSIS.
Segue o texto oficial falando sobre isso…
BUSINESS INTELLIGENCE / COMPONENTS IN ADDITIONAL SERVERS
The Business Intelligence components for SQL Server 2008 include Analysis Services, Reporting Services, and Integration Services. To use any of these components, the server on which Business Intelligence is installed must have a valid SQL Server 2008 license. If these components are in a separate server than the main database server, then they require an additional license of each additional server where they are installed.
Analysis Services 2005/2008 and ODBC Connections
Semana passada estive em um cliente para fazer uma demonstração de um Cubo no Analysis Services, tudo ia bem quando ele me questionou se seria possível conectar no AS utilizando uma conexão ODBC, pois eles gostariam de conectar no AS utilizando um software que eles já possuem.
A partir do AS 2005 não é possível fazer conexão diretamente com o AS utilizando ODBC. O recomendado é utilizar a conexão OLE DB.
Segue alguns links que tratam do assunto:
http://msdn.microsoft.com/en-us/library/ms143742(SQL.90).aspx
ODBC data sources are not supported
While previous versions of Analysis Services allowed you to use ODBC data sources, this functionality is no longer supported in Microsoft SQL Server 2005 Analysis Services.
http://technet.microsoft.com/en-us/library/aa964120(SQL.90).aspx
T-SQL/SELECT PitFall
Today I worked in a very interesting T-SQL problem…
Look at the following queries:
DECLARE @i Int, @x Int, @y VarChar(250)
SET @i = 2
SELECT @i = 1,
@x = @i + 1, — @i(1) + 1
@y = CASE
WHEN @i = 1 THEN ‘Return 1’
WHEN @i = 2 THEN ‘Return 2’
END
SELECT @x x, @y y
GO
DECLARE @i Int, @x Int, @y VarChar(250)
SET @i = 2
SELECT @i = 1,
@x = (SELECT @i + 1), — @i(2) + 1
@y = (SELECT (CASE
WHEN @i = 1 THEN ‘Return 1’
WHEN @i = 2 THEN ‘Return 2’
END))
SELECT @x x, @y y
They are very similar, the difference is that in the second batch I’m using a SubQuery to compute the value of the variables @x and @y.
As you can see, the variable @i is being used in the same SELECT instruction three times, first it receives the value “1”, then the variable @x use the variable @i and the variable @y is also using the @i.
The main point here is, this is not a good practice but, this work fine, let´s look at the results to understand the problem.
Results at SQL Server 2005 SP3, 2008 SP1 and 2008R2:

The second batch returns a different value because the SubQuery was executed first, when the value of @i was 2.
Things start to get confuse when we run it in SQL Server 2000.
Look and guess what is the results in SQL Server 2000 SP4.

Pay attention, It should be included into our migration check list, because it was changed from SQL 2000 to 2005. So, be very carefully in write/analyze these kind of queries.
Fabiano vs Dúvidas…
Hoje foi o dia das perguntas na minha caixa de e-mail… 🙂
Portanto vamos as perguntas e respostas..
1. A primeira foi perguntando sobre como fazer com que o Resource Governor direcione um usuário de um Grupo no Active Directory para um especifico Pool de Recursos.
Bom, sabemos que o gerenciamento do Resource Governor é feito por uma function de classificação. É esta function irá dizer para o Resource Governor qual pool ele deve direcionar para determinado usuário que está fazendo login no servidor.
A pergunta aqui é: Como saber se o usuário esta fazendo login é de um determinado grupo do AD ou não?
Para este questionamento respondi o seguinte e-mail:
R.: Você pode criar a function de classificação utilizando a function IS_Member()… por ex:
CREATE FUNCTION dbo.Func_Classifica()
RETURNS SYSNAME
WITH SCHEMABINDING — SCHEMA BINDING IS REQUIRED
AS
BEGIN
DECLARE @Group NVarChar(400)
SELECT @Group = CASE
WHEN ISNULL(IS_MEMBER(‘DOMINIO\Grupo_Suporte’),0) = 1 THEN ‘GrupoSuporte’
WHEN ISNULL(IS_MEMBER(‘DOMINIO\Grupo_Analistas’),0) = 1 THEN ‘GrupoAnalistas’
WHEN ISNULL(IS_MEMBER(‘DOMINIO\Grupo_Desenvolvedores’),0) = 1 THEN ‘GrupoDesenvolvedores’
WHEN ISNULL(IS_MEMBER(‘DOMINIO\Grupo_Coordenadores’),0) = 1 THEN ‘GrupoCoordenadores’
ELSE ‘Default’
END
RETURN @Group
END
GO
2. A segunda pergunta que recebi foi me questionando se existe alguma Stored Procedure do SQL que retorne o nível de compatibilidade de um banco de dados.
R.: Temos a sp_dbcmptlevel que retorna o nível de compatibilidade de um determinado banco.
Obs.: Esta function será removida do SQL em versões futuras, por isso evite usa-la. Uma alternativa seria ler esta informação direto nas tabelas do sistema do SQL.
select * from master.sys.sysdatabases
A coluna cmptlevel contém o nível de compatibilidade do banco.
3. Outro questionamento que recebi foi o seguinte. Tenho uma procedure que executa vários comandos de updates, deletes, inserts e selects, tem de tudo. Estes comandos são executados várias vezes dentro de um loop.
Eu quero ver o plano de execução destes comandos em modo gráfico, mas quando eu rodo a procedure no SSMS com a opção de exibir o plano atual(ctrl+m) ligada, ele não consegue me exibir todos os planos, e chega uma hora que o SSMS trava.
R.: Uma alternativa para visualizar estes planos em modo gráfico, seria utilizar o Profiler. Basta ler o evento Performance\ShowPlan XML. Ele irá exibir no Profiler o plano em modo gráfico, por sinal, muito show isso!
4. Por último, me perguntaram sobre qual a melhor forma de apagar uma tabela de auditoria que é BEM, aproximadamente 20GB.
R.: Sem dúvida a melhor forma seria dar um TRUNCATE TABLE na tabela, mas o truncate tem alguns pontos que devem ser considerados.
- Caso exista alguma coluna Identity na tabela, o Truncate irá zerar o Identity.
- Não da para fazer rollback.
- Não conseguira utilizar qualquer filtro utilizando a clausula WHERE.
- A tabela não pode ter foreign key ou views indexadas.
- Será necessário ter privilégio de db_ddlAdmim para rodar o Truncate.
Dito isso, com mais detalhes sobre o que o desenvolvedor queria fazer descobri que seria necessário utilizar a clausula where para excluir apenas algumas linhas. Uma alternativa para não fazer com que o LOG fique muito grande seria ir apagando os registros de pouco em pouco. Esta operação pode demorar um pouco mais do que apenas um DELETE, mas dependendo do tamanho da tabela não nos restam muitas alternativas.
Por fim enviei o seguinte comando para ele:
SET NOCOUNT ON
WHILE EXISTS(SELECT 1 FROM Auditorias_TMP)
BEGIN
BEGIN TRAN
DELETE Auditorias_TMP
FROM Auditorias_TMP
WHERE <Algum Filtro>
TABLESAMPLE(10000 ROWS)
PRINT ‘Linhas apagadas – ‘ + CONVERT(VarChar, @@ROWCOUNT )
COMMIT TRAN
END
Espero que as respostas sejam úteis para vocês…
Abraços
Posso trocar DateTime por Date?
Essa semana estou revisando meus arquivos que uso no treinamento de SQL Server que ministro, e tem um tópico onde falo da importancia de escolher os datatypes corretos para as colunas de nossas tabelas.
Isso é, quando possível, trocar BigInt por Integer, Integer por SmallInt, SmallInt por TinyInt e por ai vai…
Foi ai que cheguei na seguinte situação:
Muitas vezes podemos trocar DateTime por SmallDateTime, pois raramente precisamos dos segundos na data, e muitas vezes precisamos apenas da data, nem precisamos da hora. Isso me leva a dizer o seguinte, podemos trocar DateTime por Date, certo?…
Desta forma ganhariamos 5 bytes de espaço para cada valor gravado na coluna, pois o DateTime ocupa 8 bytes contra apenas 3 do Date. Bom dito isso chegamos onde eu queria, me diga uma coisa.
Veja que a consulta abaixo retorna:
DECLARE @Data DateTime
SET @Data = NULL
SELECT ISNULL(@Data, 0)
Ou seja, o SQL Server entende que 0 significa 1900-01-01… interessante.
Agora vamos ver o que acontece quando trocamos a variavél para Date:
DECLARE @Data Date
SET @Data = NULL
SELECT ISNULL(@Data, 0)
Msg 206, Level 16, State 2, Line 3
Operand type clash: int is incompatible with date
Conclusão, se você estiver fazendo uma conversão implicita de 0 para datetime e trocar os datatype de sua tabela de DateTime para Date, pode ser que alguns erros comecem a acontecer no seu aplicativo.
Portanto fica ai a dica, cuidado…
Removendo todas limitações do SQL Express
Galera, notícia quente.
Todos sabemos que o SQL tem varias versões e que as versões Standard/Express contêm várias limitações de recursos que só funcionam na versão Enterprise como Compression, Rebuild Online, Auto Page Recovery e etc…
A boa noticia é que existe um comando não documentado que habilita todas estas opções na versão Standard, e pasme, até na versão Express. Isso mesmo! baixe a versão express e use SEM NENHUMA RESTRIÇÃO de recursos
.
Para isso basta rodar o comando abaixo:
1: DBCC SQLPERF('Enterprise', ON)
Voilà, depois de rodar este comando você habilita todos os recursos.
Use por seu próprio risco, pois isso irá fazer com que sua licença fique ilegal!
Abraços
![]()
UPDATE
Galera, como alguns já perceberam esse era um post de 1 de Abril 🙂
, esse comando não existe.
Fico feliz em saber que muitos cairam, hahahha. Abraços.
Londres, aqui vou eu! T-SQL com o Itzik
Nos últimos 60 dias eu tenho passado os melhores dias de minha vida pois muitas coisas maravilhosas aconteceram na minha vida pessoal e profissional. O nascimento do meu filho (Felipe) com certeza foi um dos dias mais felizes de minha vida, já no âmbito profissional, eu tenho conseguido fazer tudo aquilo que sempre desejei.
Sou extremamente grato a Deus por ser um privilegiado, pois consigo trabalhar com aquilo que gosto e (sei que nem todos tem este privilégio), trabalho na empresa que considero a melhor empresa de nosso ramo (Plataforma de Dados Microsoft), a mentalidade da SolidQ realmente é diferenciada, totalmente diferente da realidade das empresas brasileiras. Cada vez que converso com um americano ou europeu vejo porque nosso país ainda é conhecido como país de terceiro mundo, precisamos mudar nossa mentalidade e investir mais em pessoas, não em processos, estudar mais para fazer melhor, com mais qualidade, mais rápido, investir para ter retorno, priorizar qualidade de vida e a família, criar um ambiente de camaradagem (isso é raro no Brasil), dar o devido valor ao conhecimento, abominar o jeitinho Brasileiro, resolver problemas não criar, “responder, não encaminhar”…
Bom outra coisa que sempre desejei desde que me conheço por pessoa foi conhecer outro país, especialmente um que sempre tive uma grande admiração, a Inglaterra, a história da Europa antiga sempre me fascinou.
Bom, terminado o meu lado pessoal do post, vamos a novidade.
Semana que vem estou indo para Inglaterra para participar e ajudar o Itzik Ben-Gan a ministrar um treinamento de T-SQL Advanced em Londres. Isso vem de encontro com nossa demanda de treinamentos de T-SQL no Brasil. Assim que eu voltar você pode esperar novidades para o Primeiro Trimestre de 2011, pois já terei aprendido com o God-Mestre, ministrado alguns treinamentos In-Company (já agendados para Dezembro), então, finalmente abriremos uma turma aberta ao publico.
Ficou interessado em conhecer o treinamento? Clique aqui para ver mais detalhes. Quer contratar o treinamento In-Company? Entre em contato comigo para conversarmos melhor sobre isso… você pode me enviar um e-mail no famorim arroba solidq ponto com
Eu agradeço novamente a Deus, porque sei que não sou merecedor de nada disso, se não fosse por Ele eu com certeza não faria parte deste projeto. Thanks Fernando, Eladio, Itzik, Diego, Felipe, Laerte, Nilton, Arnaldo, galera da CNP (Luciana (Luxo), Sandro, João, Thiago, Fernandinho, Edvaldo, Cláudio…) e todos meus amigos da comunidade SQL Server, sei que vocês ficam felizes por mim e torcem pelo sucesso da SolidQ Brazil, let’s make it happens.
Tá chegando… WorldWide Online TechDay é no Sábado (30/10)
Update*
Segue o link para download dos arquivos utilizados na WebCast…
—————————————————————————————————
Pessoal está chegando o WorldWide Online TechDay, os PPTs estão indo para o Forno, alguns já estão prontos… alguns estão sendo revisados… Muita coisa acontecendo pelos bastidores do evento que promete ser o maior evento online que o Brasil já viu.
Como vocês já sabem, minha sessão será no Sábado dia 30 as 10:00 horas da manhã, e vou falar sobre como cortar a gordura do seu banco de dados.
Segue o link para a inscrição do evento.
Gostou do tema? Então vai algumas imagens do PPT que irei utilizar no sábado:
Ficou interessado?
Não deixe de participar da minha sessão, e das outras sessões que irão acontecer no evento… Clique aqui para ver todos os links para inscrição dos eventos…
Abraços e até sábado.
T-SQL Query – NTILE()
Hoje recebi no e-mail uma pergunta bem interessante sobre T-SQL…
O desenvolvedor tem um processo bem lento que é executado de acordo com uma faixa inicial e final que são recebidas como parâmetro de entrada para uma procedure.
Ex:
EXEC dbo.st_Process @ID_Inicio = ‘1’, @ID_Fim = ‘10000’
Ou seja, na query acima, o processo irá rodar para os ids 1 até 10000.
Mas o desenvolvedor quer rodar o processo em aproximadamente 50 em 50 ids.
Por exemplo:
EXEC dbo.st_Process @ID_Inicio = ‘1’, @ID_Fim = ’50’
EXEC dbo.st_Process @ID_Inicio = ’51’, @ID_Fim = ‘100’
EXEC dbo.st_Process @ID_Inicio = ‘101’, @ID_Fim = ‘150’
…
Agora eis a questão. Como fazer para criar uma consulta que pega a tabela, #Tab1 e gera uma lista com os grupos a serem executados?
SET NOCOUNT ON
IF OBJECT_ID(‘tempdb.dbo.#Tab1’) IS NOT NULL
DROP TABLE #Tab1
GO
CREATE TABLE #Tab1 (ID Int IDENTITY(1,1))
GO
INSERT INTO #Tab1 DEFAULT VALUES
GO 10000
SELECT * FROM #Tab1
GO
Preciso que isso:
Vire isso:
Para resolver esta consulta, fiz uma query utilizando o NTILE para quebrar os grupos.
DECLARE @i Int
SELECT @i = COUNT(*) / 50
FROM #Tab1
SELECT Groups, MIN(ID) AS ID_Inicio, MAX(ID) AS ID_Fim
FROM (SELECT NTILE(@i) OVER(ORDER BY ID) AS Groups, ID
FROM #Tab1) AS Tab
GROUP BY Groups
E você? Teria outra solução mais simples? Abraços…





