Tenho lógica substituindo caracteres por ''
:
DECLARE
v_owner VARCHAR2(50) := 'LFS_SURVEY'; -- Replace with your schema/owner name
v_table_name VARCHAR2(50) := 'LFS_FAMILY_TAB'; -- Replace with your table name
v_rp_ids VARCHAR2(100) := '2030, 2031'; -- Replace with your RP_ID values
v_columns CLOB;
v_query CLOB;
BEGIN
-- Get all column names with transformations based on data type
EXECUTE IMMEDIATE 'SELECT RTRIM(XMLAGG(XMLELEMENT(e,
CASE
WHEN COLUMN_NAME = ''F_M_ID'' THEN ''TO_CHAR(t.F_M_ID) AS F_M_ID''
WHEN DATA_TYPE LIKE ''%CHAR%'' THEN ''REPLACE(REPLACE(t.'' || COLUMN_NAME || '', CHR(13), ''''), CHR(10), '''') AS '' || COLUMN_NAME
ELSE ''t.'' || COLUMN_NAME
END || '', '').EXTRACT(''//text()'') ORDER BY COLUMN_ID).GETCLOBVAL(), '', '')
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = ''' || v_table_name || '''
AND OWNER = ''' || v_owner || ''''
INTO v_columns;
DBMS_OUTPUT.PUT_LINE(v_columns);
END;
/
A saída mostra '
em vez de ''
, por exemplo:
REPLACE(REPLACE(t.Q_851, CHR(13), &appos;), CHR(10), &appos;) AS Q_851
Como posso forçar a impressão ''
?
Como uma string vazia
''
é equivalente anull
no Oracle, neste caso você pode evitar o problema substituindo tabulação/nova linha por nulo; então, em vez disso:faça isso:
Você não precisa usar SQL dinâmico aqui, pois pode consultar estaticamente o dicionário de dados - o esquema de destino/nome da tabela são variáveis aqui, não identificadores:
Com uma tabela fictícia criada como:
que produz:
violino
E isso é funcionalmente o mesmo que
Se você realmente quiser
''
(null
ou talvez tiver que lidar com outros literais de texto), você pode usar XMLTable, que não escapa de entidades comoextract
(e XMLQuery):que para a mesma tabela fictícia gera:
violino
A propósito, seu código original produz
'
, mas isso é apenas uma aspa com escape de entidade'
. Se você quisesse duas''
, precisaria de ainda mais em seu código:Mas isso
''
não resolveria o problema, mesmo que você desfaça o escape manualmente dessas entidades.O Oracle representa 4 aspas simples consecutivas como uma aspa simples. Então, talvez a maneira mais legível ao construir algum sql dinâmico seria declarar uma variável de aspas simples
sq VARCHAR2(1) := '''';
como abaixo:
OBSERVAÇÃO:
Dessa forma, você pode inserir sq (ou dois, três deles) em qualquer lugar da string e manter o código legível e sustentável...
Por que 4 para obter 1?
violino
Existem algumas técnicas pl/sql que simplificarão seu código e reduzirão as chances de encontrar problemas como o seu. Como outros indicaram, isso
EXECUTE IMMEDIATE
não é necessário neste caso em particular, mas se você escolher fazer isso de qualquer maneira, aqui estão algumas dicas.citação alternativa também conhecida como sintaxe Q-quote
Isso permite que você use outro delimitador de string diferente de aspas simples - eliminando assim a necessidade de escape de aspas ( docs )
Exemplo:
use variáveis de ligação, não concatenação
Conectar valores de variáveis em pl/sql e sql não é uma boa prática. Isso torna o código vulnerável à injeção de sql. Além disso, é difícil de ler e um pesadelo para manter (como você mostrou). Tente usar variáveis bind sempre que possível. É uma codificação melhor e muito mais legível.
Exemplo: