Dicas para SQL Dinâmico - Apóstrofos
Olá pessoal.
A dica de hoje vai para quem precisa construir comandos SQL dinâmicos, seja dentro de stored procedures ou diretamente no código da sua linguagem de preferência. Vou usar Oracle para o exemplos, mas o conceito também se aplica ao SQL Server. Para deixar os posts menores, vou fazer cada dica um post diferente.
Apóstrofo (ou aspas simples)
Todo mundo sabe que, em uma instrução SQL, as strings são delimitadas por apóstrofo (que alguns chamam de aspas simples). Assim:
Agora vamos adicionar um pouco de complexidade ao exemplo. Vou transformar esse pequeno bloco anônimo numa stored procedure com dois parâmetros do tipo string, que serão usados para preencher col1 e col2.
"ruim" apenas como exemplo de manipulação de strings. Outro dia eu falo sobre binding vars.
Repare como os diversos apóstrofos colados começam a prejudicar a leitura do código da proc. E é apenas uma linha de código!!! Imagine um insert imenso com muitas colunas string, o comando quebrado em várias linhas... Começa a ficar realmente ruim.
Para deixar o código mais limpo (facilitar a leitura), eu vou substituir cada apóstrofo duplicado (aqueles de dentro da string, e somente esses!) por uma aspa comum (ou dupla, se preferir). Percebe que um apóstrofo duplicado ('') não é a mesma coisa que uma aspa ("). São caracteres diferentes!!!.
Mais fácil para identificar onde começa e onde termina cada string (cada "pedaço" do comando SQL).
Só que se você executar esta proc, vai dar erro. Isto porque as aspas não são aceitas (em PL/SQL nem T-SQL) como delimitadores de string.
A correção é bem simples: Pode usar aspas à vontade dentro da sua string e, no último momento antes de executar o comando, você converte todas as aspas para apóstrofos duplos.
Há uma restrição que você não pode usar aspas para nenhum outro fim, dentro do seu comando SQL. Se você puder atender este requisito, está feito. E eu particularmente não considero uma coisa muito esperta usar aspas (") nos nomes dos objetos Oracle. Serve só para dar dor-de-cabeça, mas isso também é papo para outro dia.
É isso pessoal.
Espero que sirva de ajuda para alguém por aí.
Abraços,
LZ
A dica de hoje vai para quem precisa construir comandos SQL dinâmicos, seja dentro de stored procedures ou diretamente no código da sua linguagem de preferência. Vou usar Oracle para o exemplos, mas o conceito também se aplica ao SQL Server. Para deixar os posts menores, vou fazer cada dica um post diferente.
Apóstrofo (ou aspas simples)
Todo mundo sabe que, em uma instrução SQL, as strings são delimitadas por apóstrofo (que alguns chamam de aspas simples). Assim:
create table tab_a (col1 varchar2(100) not null, col2 varchar2(100) not null);
declare
minha_string varchar2(1000);
begin
minha_string := 'isso é uma string';
end;
/
Muito bem. Mas e se a string em questão for uma instrução SQL? Ela, por natureza é uma linha de texto e que pode ter uma string dentro. Imagine o comando:declare
minha_string varchar2(1000);
begin
minha_string := 'isso é uma string';
end;
/
insert into tab_A (col1, col2) values ('valor 1', 'valor 2');
Se esse comando for uma instrução SQL dinâmica, você teria algo como isso:declare
meu_sql varchar2(1000);
begin
meu_sql := 'insert into tab_A (col1, col2) values (''valor 1'', ''valor 2'')';
end;
/
Repare que para reproduzir um apóstro dentro de uma string, eu tenho que duplicá-lo, porque ele é um caracter especial (delimitador de string). Se colocasse sem duplicar, o compilador ia acusar erro, achando que haveria strings em sequencia, sem concatenar, nem nada. meu_sql varchar2(1000);
begin
meu_sql := 'insert into tab_A (col1, col2) values (''valor 1'', ''valor 2'')';
end;
/
Agora vamos adicionar um pouco de complexidade ao exemplo. Vou transformar esse pequeno bloco anônimo numa stored procedure com dois parâmetros do tipo string, que serão usados para preencher col1 e col2.
create or replace procedure proc_exemplo (pCol1 in varchar2, pCol2 in varchar2) as
vSQL varchar2(1000);
begin
vSQL := 'insert into tab_A (col1, col2) values (''' || pCol1 || ''', ''' || pCol2 || ''')';
execute immediate vSQL;
end;
/
Sabemos que usar variáveis de ligação é muito mais eficiente, mas resolvi adotar esta estratéria vSQL varchar2(1000);
begin
vSQL := 'insert into tab_A (col1, col2) values (''' || pCol1 || ''', ''' || pCol2 || ''')';
execute immediate vSQL;
end;
/
"ruim" apenas como exemplo de manipulação de strings. Outro dia eu falo sobre binding vars.
Repare como os diversos apóstrofos colados começam a prejudicar a leitura do código da proc. E é apenas uma linha de código!!! Imagine um insert imenso com muitas colunas string, o comando quebrado em várias linhas... Começa a ficar realmente ruim.
Para deixar o código mais limpo (facilitar a leitura), eu vou substituir cada apóstrofo duplicado (aqueles de dentro da string, e somente esses!) por uma aspa comum (ou dupla, se preferir). Percebe que um apóstrofo duplicado ('') não é a mesma coisa que uma aspa ("). São caracteres diferentes!!!.
create or replace procedure proc_exemplo (pCol1 in varchar2, pCol2 in varchar2) as
vSQL varchar2(1000);
begin
vSQL := 'insert into tab_A (col1, col2) values ("' || pCol1 || '", "' || pCol2 || '")';
execute immediate vSQL;
end;
/
Mais fácil de ler, não?vSQL varchar2(1000);
begin
vSQL := 'insert into tab_A (col1, col2) values ("' || pCol1 || '", "' || pCol2 || '")';
execute immediate vSQL;
end;
/
Mais fácil para identificar onde começa e onde termina cada string (cada "pedaço" do comando SQL).
Só que se você executar esta proc, vai dar erro. Isto porque as aspas não são aceitas (em PL/SQL nem T-SQL) como delimitadores de string.
A correção é bem simples: Pode usar aspas à vontade dentro da sua string e, no último momento antes de executar o comando, você converte todas as aspas para apóstrofos duplos.
create or replace procedure proc_exemplo (pCol1 in varchar2, pCol2 in varchar2) as
vSQL varchar2(1000);
begin
-- preparando o comando SQL
vSQL := 'insert into tab_A (col1, col2) values ("' || pCol1 || '", "' || pCol2 || '")';
-- fazendo os ultimos ajustes antes de executar
vSQL := replace(vSQL, '"', '''');
execute immediate vSQL;
end;
/
A linha do replace é a única que você terá que manter bagunçada (vários caracteres apóstrofo), mas como é uma linha só, que fica só no final do bloco de código, dá para conviver.vSQL varchar2(1000);
begin
-- preparando o comando SQL
vSQL := 'insert into tab_A (col1, col2) values ("' || pCol1 || '", "' || pCol2 || '")';
-- fazendo os ultimos ajustes antes de executar
vSQL := replace(vSQL, '"', '''');
execute immediate vSQL;
end;
/
Há uma restrição que você não pode usar aspas para nenhum outro fim, dentro do seu comando SQL. Se você puder atender este requisito, está feito. E eu particularmente não considero uma coisa muito esperta usar aspas (") nos nomes dos objetos Oracle. Serve só para dar dor-de-cabeça, mas isso também é papo para outro dia.
É isso pessoal.
Espero que sirva de ajuda para alguém por aí.
Abraços,
LZ
Marcadores: apostrofo, apostrofo no sql, aspas, aspas duplas, aspas simples, oracle, sql dinamico
1 Comentários:
Show de bola, usei a idéia de trocar apóstrofo por aspas simples e depois dar um replace, foi o que me salvou aqui. Assunto muito útil!
Por Alexandre Nascimento, Às 2 de fevereiro de 2011 às 17:53
Postar um comentário
Assinar Postar comentários [Atom]
<< Página inicial