Usando uma Variável dentro do from

08/07/2021

0

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?
Rafael Biazetto

Rafael Biazetto

Responder

Posts

08/07/2021

Emerson Nascimento

estude o comando sp_executesql



Responder

09/07/2021

Rafael Biazetto

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





Responder

10/07/2021

Emerson Nascimento

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
Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar