Usando uma Variável dentro do from
Pessoal, bom dia.
Estou exercitando o SQL e estou reescrevendo uma query de outro DBA.
e para minha logica funcionar eu preciso fazer um select onde o from vai pesquisar uma tabela que esta dentro de uma variavel.
Para exemplificar o que preciso fazer escrevi esse exemplo a baixo:
declare @x varchar(8) --declarei a variável
set @x = 'RCN010' -- Atribui um valor para a Variável
select @x --Visualizei o conteúdo da variável
SELECT * FROM @x -- eu desejo visualizar o conteúdo da tabela que foi informada dentro da variável
-- o SQL retorna o seguinte erro : Must declare the table variable "@x".
alguém pode me ajudar?
Estou exercitando o SQL e estou reescrevendo uma query de outro DBA.
e para minha logica funcionar eu preciso fazer um select onde o from vai pesquisar uma tabela que esta dentro de uma variavel.
Para exemplificar o que preciso fazer escrevi esse exemplo a baixo:
declare @x varchar(8) --declarei a variável
set @x = 'RCN010' -- Atribui um valor para a Variável
select @x --Visualizei o conteúdo da variável
SELECT * FROM @x -- eu desejo visualizar o conteúdo da tabela que foi informada dentro da variável
-- o SQL retorna o seguinte erro : Must declare the table variable "@x".
alguém pode me ajudar?
Rafael Biazetto
Curtidas 0
Respostas
Emerson Nascimento
08/07/2021
estude o comando sp_executesql
GOSTEI 0
Rafael Biazetto
08/07/2021
estude o comando sp_executesql
Emerson, obrigado pela atenção.
Eu li a documentação da Microsoft sobre esse comendo mas não consegui encaixar ele na minha necessidade.
Vou colocar a baixo o que tenho escrito até o momento para você enxergar meu exercício.
dentro do sistema Protheus quando deletamos um registro via sistema o registro não é deletado da tabela, tem um campo chamado D_E_L_E_T_ e esse campo recebe um * para indicar que o registro foi deletado então a aplicação não apresenta esse registro nas pesquisas.
no enteando as tabelas de contabilidade por exemplo chegam a 30 milhões de registros e em alguns casos metade dos registros estão com o campo D_E_L_E_T_ com *
para reduzir o tamanho do banco de dados tem uma ferramenta dentro do sistema que efetivamente deleta o registro da tabela quando o campo D_E_L_E_T_ esta com *
mas isso tem que ser feito tabela por tabela
então eu pensei em fazer uma query no sql server para fazer isso no banco todo
uma boa parte eu já consegui fazer, na verdade o que eu quero fazer já esta pronto
a minha query ja esta criando o comando de delet para eu apagar esses registro marcados com * porem eu quero criar um relatório onde informa:
- A quantidade de registros de cada tabela no campo REGISTROS
- A quantidade de registros deletados no campo DELETADOS
São esses dois requisitos que eu não estou conseguindo fazer.
Seque a query que eu escrevi:
-- criando tabela de apoio:
create table REGDELET (TABELA_SIGA VARCHAR(7), REGISTROS INT, DELETADOS INT, COMANDO VARCHAR(100))
--declarando as variáveis para apoio do cursor
declare @nome_tabela varchar(6)
declare @total_reg int
declare @delet int
-- criando cursor ** nesse momento estou criando a select que vai apresentar os dados filtrados que eu desejo.
--o cursor vai percorrer esses dados e fazer processos em cada linha desses dados. no select a baixo temos
--retornado todas as tabelas do protheus pesquisadas nas tabelas de sistema do sql server sys.objects e sys.columns.
--usei essas duas tabelas para ter certeza de que só trará as tabelas do protheus
declare cur_delet cursor
for SELECT distinct sys.objects.name
FROM sys.objects inner join sys.columns
on sys.objects.object_id = sys.columns.object_id
where type = 'U' and sys.columns.name = 'D_E_L_E_T_'
-- abrindo o cursor
open cur_delet
-- selecionar os dados
fetch next from cur_delet
into @nome_tabela
while @@FETCH_STATUS = 0
begin
set @total_reg = (SELECT COUNT(*) FROM (SELECT @nome_tabela as tabela) a)
set @delet = (SELECT COUNT(*) FROM (SELECT @nome_tabela as tabela) as b)
INSERT INTO REGDELET (TABELA_SIGA , REGISTROS , DELETADOS , COMANDO)
values (@nome_tabela, @total_reg, @delet, (select 'DELETE FROM '+ @nome_tabela + ' WHERE D_E_L_E_T_ = '+'*'))
--select 'DELETE FROM TABLE '+ @nome_tabela + ' WHERE D_E_L_E_T_ = '+'*'
fetch next from cur_delet
into @nome_tabela
end
close cur_delet
deallocate cur_delet
quando eu executo essa query e rodo um select na tabela REGDELET
SELECT TOP(3) * FROM REGDELET
TABELA_SIGA REGISTROS DELETADOS COMANDO
----------- ----------- ----------- ----------------------------------------------------------------------------------------------------
CTT010 1 1 DELETE FROM CTT010 WHERE D_E_L_E_T_ = *
MP1010 1 1 DELETE FROM MP1010 WHERE D_E_L_E_T_ = *
MP1040 1 1 DELETE FROM MP1040 WHERE D_E_L_E_T_ = *
meu problema esta nesse trecho:
set @total_reg = (SELECT COUNT(*) FROM (SELECT @nome_tabela as tabela) a)
set @delet = (SELECT COUNT(*) FROM (SELECT @nome_tabela as tabela) as b)
Acho que agora ficou mais claro a minha necessidade
GOSTEI 0
Emerson Nascimento
08/07/2021
a necessidade já estava clara.
--cria a tabela de apoio create table REGDELET (TABELA_SIGA VARCHAR(50), REGISTROS INT, DELETADOS INT, COMANDO VARCHAR(200)) --declarando as variáveis para apoio do cursor declare @nome_tabela varchar(50) declare @total_reg int declare @delet int declare @comandosql as nvarchar(max) declare @parametros as nvarchar(max) -- criando cursor. nesse momento estou criando a select que vai apresentar os dados filtrados que eu desejo. -- o cursor vai percorrer esses dados e fazer processos em cada linha desses dados. no select abaixo temos -- retornado todas as tabelas do protheus pesquisadas nas tabelas de sistema do sql server sys.objects e sys.columns. -- usei essas duas tabelas para ter certeza de que só trará as tabelas do protheus declare cur_delet cursor local for SELECT distinct sys.objects.name FROM sys.objects inner join sys.columns on sys.objects.object_id = sys.columns.object_id where type = 'U' and sys.columns.name = 'D_E_L_E_T_' -- abrindo o cursor open cur_delet -- selecionando os dados fetch next from cur_delet into @nome_tabela while @@FETCH_STATUS = 0 begin -- conta o número total de registros e o número de registros deletados -- precisa criar uma query dinâmica para execução através da procedure sp_executesql set @comandosql = 'select @total_regOUT = count(*), '+ '@deletOUT = count(case when D_E_L_E_T_ = ''*'' then 1 else null end) from '+@nome_tabela set @parametros = '@total_regOUT integer OUTPUT, @deletOUT integer OUTPUT'; execute sp_executesql @comandosql, @parametros, @total_regOUT=@total_reg OUTPUT, @deletOUT=@delet OUTPUT; -- insere os dados na tabela REGDELET -- somente efetua a inserção caso haja registros deletados (D_E_L_E_T_ = '*') -- não avalia duplicidade; no caso da tabela já existir na REGDELET ela será 'duplicada' if (@delet > 0) INSERT INTO REGDELET(TABELA_SIGA, REGISTROS, DELETADOS, COMANDO) values (@nome_tabela, @total_reg, @delet, 'DELETE FROM '+ @nome_tabela + ' WHERE D_E_L_E_T_ = ''*''') -- lê a próxima linha do cursor fetch next from cur_delet into @nome_tabela end -- fecha o cursor e libera o a memória alocada close cur_delet deallocate cur_delet
GOSTEI 0