Concatenar conteúdo de um registro SQL Server 2005

13/05/2015

0

Boa tarde,

Estou com uma necessidade de retornar o conteúdo de um registro de uma determinada tabela. Exemplo:

Tenho uma tabela de PRODUTOS com os seguintes campos:

CODIGO NOME MARCA VALOR
------------ -------------------------------- -------------- ---------
2514 MOUSE 3 BOTOES USB LOGITECH 45,00


Gostaria de saber se existe algum comando SQL ou Função ou StoreProcedure para que ao passar o nome da tabela como parâmetro a mesma me retorne o conteúdo do registro devidamente concatenado. Seguindo o exemplo do registro acima ficaria assim:
2514MOUSE 3 BOTÕES USBLOGITECH45,00

Atualmente estou utilizando uma função em Delphi7 para essa finalidade mas devido a alguns clientes terem muitos registros esta um pouco lento.


if not QAux.FieldByName(CampoChave).IsNull then
begin
//Loop nos Fields
for i := 0 to QAux.FieldCount -1 do
begin
if QAux.FieldDefs[i].Name <> NomeCampo then //elimina o campo _HASH para que o mesmo não faça parte do calculo MD5
StringAux := StringAux + QAux.Fields.Fields[i].AsString;
end;
end;


Minha necessidade desta rotina é para atender um requisito do PAF-ECF para detectar se houve algum tipo de manipulação no banco de dados que não passou pelo meu sistema.
Carlos Eduardo

Carlos Eduardo

Responder

Post mais votado

13/05/2015

Um detalhe, pode usar o convert em campos que já sao do tipo varchar que não da erro.


Vou testar a consulta sql e assim que possível postarei o resultado.

Grato pela contribuição.

Carlos Eduardo

Carlos Eduardo
Responder

Mais Posts

14/05/2015

Marcos P

Já é um avanço...

Vai ser necessário debug do código Delphi !

O Delphi gera algum erro ou somente não retorna nada ?

Caso retorne erro, cole ele aqui...

Caso não retorne, você provavelmente está chamando errado a SP...
> Confirme certinho a passagem de parâmetros para a procedure...
> Abra um "Sql Profiler" no server e debug a chamada à procedure...
> Pegue o comando gerado no banco e rode no Management Studio... ajustando a sintaxe de chamada no Delphi, até ficar certo !
Responder

14/05/2015

Marcos P

Em tempo... qual a versão do seu Delphi ?

Se for superior a 7, troque a passagem de parâmetros "AsString", para : "AsAnsiString".
Responder

14/05/2015

Carlos Eduardo

Estou utilizando o Delphi 7.

O engraçado é que antes quando estava com a linha abaixo na SP estava retornando pelo Delphi normalmente porém não com o conteúdo que preciso.

select @Resultado = (@SQL + ' from ' + @nome_tabela + ' where ' + @campo_chave + ' = ' + @codigo)


Não está ocorrendo erro.

Estou utilizando o DBExpress tentarei usar o ADO para fim de testes.

Qualquer novidade posto aqui.

Grato!
Responder

14/05/2015

Marcos P


Não consegui fazer com que este procedimento me retornasse o resultado do select mas sim a instrução sql. Exemplo: "select campo1, campo2 from PRODUTOS"


Não entendi...

Conforme você mesmo disse a query anterior ( com select @Resultado ), não estava funcionando... pois retornava a instrução e não os dados !

Agora, você afirma que estava retornando normalmente no Delphi...

Você chegou a fazer o debug no banco ?

O execute está sendo gerado corretamente, pelo Delphi ?
Responder

14/05/2015

Carlos Eduardo

Marcos, desculpe a confusão... mas na verdade o que eu quis dizer e que no Delphi que não mais esta pegando o retorno do procedimento. O procedimento em si quando executo pelo SQL Management Studio esta OK.

Vou postar o código do Delphi que estou tendo problemas com o retorno do procedimento. O parâmetro "@resultado" esta retornando vazio.

  try
    try
      sp_Retorna_Conteudo_Registro := TSQLStoredProc.Create(nil);
      sp_Retorna_Conteudo_Registro.SQLConnection  := AutoConnection;
      sp_Retorna_Conteudo_Registro.SchemaName     := 'dbo';
      sp_Retorna_Conteudo_Registro.StoredProcName := 'sp_Retorna_Conteudo_Registro';
      sp_Retorna_Conteudo_Registro.Params.FindParam('@nome_tabela').AsString := lbledtTabela.Text;
      sp_Retorna_Conteudo_Registro.Params.FindParam('@campo_chave').AsString := lbledtChave.Text;
      sp_Retorna_Conteudo_Registro.Params.FindParam('@codigo').AsString      := lbledtCodigo.Text;
      sp_Retorna_Conteudo_Registro.ExecProc;
      lbledtResultSP.Text := sp_Retorna_Conteudo_Registro.Params.FindParam('@resultado').AsString;
    finally
      FreeAndNil(sp_Retorna_Conteudo_Registro);
    end;
  except on E: Exception do
    Application.MessageBox(PChar(E.Message), 'Erro', MB_ICONERROR);
  end
Responder

15/05/2015

Marcos P

Crie o componente em tempo de design, revise a declaração de parâmetros ( inclusive o result ) e tente ajustar o código para :
( assumindo que a SP tem somente três parâmetros )
try
  sp_Retorna_Conteudo_Registro.Close;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@nome_tabela').AsAnsiString := lbledtTabela.Text;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@campo_chave').AsAnsiString := lbledtChave.Text;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@codigo').AsAnsiString      := lbledtCodigo.Text;
  sp_Retorna_Conteudo_Registro.ExecProc;
  ShowMessage('Registros retornados : '+ IntToStr(sp_Retorna_Conteudo_Registro.RecordCount));
except on E: Exception do
  Application.MessageBox(PChar(E.Message), 'Erro', MB_ICONERROR);
end;
Responder

17/05/2015

Carlos Eduardo

Crie o componente em tempo de design, revise a declaração de parâmetros ( inclusive o result ) e tente ajustar o código para :
( assumindo que a SP tem somente três parâmetros )
try
  sp_Retorna_Conteudo_Registro.Close;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@nome_tabela').AsAnsiString := lbledtTabela.Text;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@campo_chave').AsAnsiString := lbledtChave.Text;
  sp_Retorna_Conteudo_Registro.Params.ParamByName('@codigo').AsAnsiString      := lbledtCodigo.Text;
  sp_Retorna_Conteudo_Registro.ExecProc;
  ShowMessage('Registros retornados : '+ IntToStr(sp_Retorna_Conteudo_Registro.RecordCount));
except on E: Exception do
  Application.MessageBox(PChar(E.Message), 'Erro', MB_ICONERROR);
end;


Boa noite Marcos,

Fiz isso tudo que você disse, mas ao passar no RecordCount da esse erro:
dbExpress Error: Operation Not Supported


OBS: Testei também no XE2.

Fiz testes na SP e também cheguei a criar uma função para testes mas ambas consegui retornar de tudo, menos o resultado do select "exec(@SQL)".

Só consegui o que eu queria realizando em duas etapas:
1) Criei uma função que retorne o select. Ex: "select prd_codigo + prd_nome + prd_marca, etc... from PRODUTOS where PRD_CODIGO = 1"
2) Depois peguei o resultado deste select e mandei executar outra consulta.

Tudo isso via Delphi. Vou postar minha função e um pedaço do código em Delphi para conhecimento. Mas ainda não sei se vai valer a pena fazer uso destes procedimentos, pois depois disso tudo ainda tenho que utilizar uma rotina que me retorna o MD5 do conteúdo para saber se houve ou não manipulação no banco de dados.

Vou finalizar este post, mas em breve vou criar um novo para que alguém possa me ajudar de outra forma como identificar se houve manipulação no banco de dados que não passou pelo meu sistema.

Grato!

Código da Função:
CREATE FUNCTION [dbo].[fc_Retorna_Conteudo_Registro](
@nome_tabela varchar(50),
@campo_chave varchar(50),
@codigo varchar(10))
RETURNS varchar(5000)
AS
BEGIN
declare cursorcolumns cursor for
  select column_name, data_type 
  from information_schema.columns 
  where table_name = @nome_tabela
  and (column_name not like '%HASH')
  
declare @column_name varchar(100), @data_type varchar(100), @SQL varchar(5000)
set @SQL = 'select '
open cursorcolumns

fetch next from cursorcolumns into @column_name, @data_type

while (@@FETCH_STATUS = 0)
begin
  if @data_type in ('char', 'nchar', 'nvarchar', 'varchar')
    set @SQL = @SQL + 'coalesce(' + @column_name + ','''') + '
  else
    if @data_type in ('datetime', 'date')
      set @SQL = @SQL + 'Convert(Varchar(10), ' + @column_name + ',103) + '
    else
      if @data_type = ('decimal')
        set @SQL = @SQL + 'case when (' + @column_name + ' = 0) or (' + @column_name + ' is null) then ''0''' +
                          'else                          convert(varchar,' + @column_name + ')' +
                          'end + '
      else
        set @SQL = @SQL + 'coalesce(convert(varchar(8000), ' + @column_name + '),'''') + '
  fetch next from cursorcolumns into @column_name, @data_type
end
close cursorcolumns
deallocate cursorcolumns

if right(@SQL,2) = '+ '  --remove o caracter "+" resultado da concatenação no loop dos campos
   set @SQL = left(@SQL,(len(@SQL)-1)) 

RETURN (@SQL + 'as Conteudo from ' + @nome_tabela + ' where ' + @campo_chave + ' = ' + @codigo)

END


Código Delphi
  try
    SQLQuery1.Close;
    SQLQuery1.SQL.Text := 'select dbo.fc_Retorna_Conteudo_Registro(''PRODUTOS'', ''PRD_CODIGO'', ''1'') as Resultado';
    SQLQuery1.Open;

    SQL := SQLQuery1.FieldByName('Resultado').AsString;

    SQLQuery1.Close;
    SQLQuery1.SQL.Text := SQL;
    SQLQuery1.Open;
    mmoResultSP.Text := SQLQuery1.FieldByName('Conteudo').AsString;
    SQLQuery1.Close;
  except on E: Exception do
    Application.MessageBox(PChar(E.Message), 'Erro', MB_ICONERROR);
  end
Responder

17/05/2015

Marcos P

A solução que você deu é equivalente a criação da procedure e, portanto, perfeitamente funcional... devendo resolver seu problema original de performance.

Quanto ao MD5, você consegue gerá-lo no próprio Sql Server. Existem funções na WEB disponíveis para isso... vale uma pesquisada !
Responder

17/05/2015

Carlos Eduardo

A solução que você deu é equivalente a criação da procedure e, portanto, perfeitamente funcional... devendo resolver seu problema original de performance.

Quanto ao MD5, você consegue gerá-lo no próprio Sql Server. Existem funções na WEB disponíveis para isso... vale uma pesquisada !


Marcos, realmente é equivalente sim, mas achei melhor criar uma função por ser mais fácil sua utilização no Delphi.

Referente ao MD5 vou dar uma pesquisada sim. Quando eu tiver um resultado satisfatório postarei aqui a solução encontrada e se realmente obtive uma melhora na performance que é meu objetivo final.

Grato pela ajuda, pois foi de grande valia.
Responder

Que tal ter acesso a um e-book gratuito que vai te ajudar muito nesse momento decisivo?

Ver ebook

Recomendado pra quem ainda não iniciou o estudos.

Eu quero
Ver ebook

Recomendado para quem está passando por dificuldades nessa etapa inicial

Eu quero

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

Aceitar