Concatenar conteúdo de um registro SQL Server 2005
13/05/2015
0
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
Post mais votado
13/05/2015
Vou testar a consulta sql e assim que possível postarei o resultado.
Grato pela contribuição.
Carlos Eduardo
Mais Posts
14/05/2015
Marcos P
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 !
14/05/2015
Marcos P
Se for superior a 7, troque a passagem de parâmetros "AsString", para : "AsAnsiString".
14/05/2015
Carlos Eduardo
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!
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 ?
14/05/2015
Carlos Eduardo
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
15/05/2015
Marcos P
( 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;
17/05/2015
Carlos Eduardo
( 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:
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
17/05/2015
Marcos P
Quanto ao MD5, você consegue gerá-lo no próprio Sql Server. Existem funções na WEB disponíveis para isso... vale uma pesquisada !
17/05/2015
Carlos Eduardo
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.
Clique aqui para fazer login e interagir na Comunidade :)