这就是我的用例:输入是一个字符串,表示仲裁复杂性的Oracle /SQL语句。我们可能假设它是一个语句(而不是脚本)。现在,这个输入字符串的几个位必须重写。
例如,表名需要前缀,不使用列别名的选择列表中的聚合函数应该被指定为默认的函数:
SELECT SUM(ABS(x.value)),
TO_CHAR(y.ID,'111,111'),
y.some_col
FROM
tableX x,
(SELECT DISTINCT ID
FROM tableZ z
WHERE ID > 10) y
WHERE
...变成了
SELECT SUM(ABS(x.value)) COL1,
TO_CHAR(y.ID,'111,111') COL2,
y.some_col
FROM
pref.tableX x,
(SELECT DISTINCT ID, some_col
FROM pref.tableZ z
WHERE ID > 10) y
WHERE
...(免责声明:只是为了说明问题,声明没有意义)
由于聚合函数可能是嵌套的,而subSELECT是一个b_tch,所以我不敢使用正则表达式。嗯,事实上我做到了,并且取得了80%的成功,但我确实需要剩下的20%。
我认为正确的方法是使用语法和解析器。我摆弄着c++ ANTLR2 (尽管在这样的帮助下,我对语法和解析不太了解)。我看不出获得SQL位的一种简单方法:
list<string> *ssel = theAST.getSubSelectList(); // fantasy land有人能提供一些关于“解析专业人士”将如何解决这个问题的建议吗?编辑:我正在使用Oracle9i。
发布于 2009-10-23 17:24:44
也许您可以使用它,它将select语句更改为xml块:
declare
cl clob;
begin
dbms_lob.createtemporary (
cl,
true
);
sys.utl_xml.parsequery (
user,
'select e.deptno from emp e where deptno = 10',
cl
);
dbms_output.put_line (cl);
dbms_lob.freetemporary (cl);
end;
/
<QUERY>
<SELECT>
<SELECT_LIST>
<SELECT_LIST_ITEM>
<COLUMN_REF>
<SCHEMA>MICHAEL</SCHEMA>
<TABLE>EMP</TABLE>
<TABLE_ALIAS>E</TABLE_ALIAS>
<COLUMN_ALIAS>DEPTNO</COLUMN_ALIAS>
<COLUMN>DEPTNO</COLUMN>
</COLUMN_REF>
....
....
....
</QUERY>见此处:�
现在,您只需要解析这个xml块。
Edit1:
遗憾的是,我并不完全理解OP的需求,但我希望这能有所帮助(这是询问例如查询select count(*),max(dummy) from dual的列的“名称”的另一种方式):
set serveroutput on
DECLARE
c NUMBER;
d NUMBER;
col_cnt PLS_INTEGER;
f BOOLEAN;
rec_tab dbms_sql.desc_tab;
col_num NUMBER;
PROCEDURE print_rec(rec in dbms_sql.desc_rec) IS
BEGIN
dbms_output.new_line;
dbms_output.put_line('col_type = ' || rec.col_type);
dbms_output.put_line('col_maxlen = ' || rec.col_max_len);
dbms_output.put_line('col_name = ' || rec.col_name);
dbms_output.put_line('col_name_len = ' || rec.col_name_len);
dbms_output.put_line('col_schema_name= ' || rec.col_schema_name);
dbms_output.put_line('col_schema_name_len= ' || rec.col_schema_name_len);
dbms_output.put_line('col_precision = ' || rec.col_precision);
dbms_output.put_line('col_scale = ' || rec.col_scale);
dbms_output.put('col_null_ok = ');
IF (rec.col_null_ok) THEN
dbms_output.put_line('True');
ELSE
dbms_output.put_line('False');
END IF;
END;
BEGIN
c := dbms_sql.open_cursor;
dbms_sql.parse(c,'select count(*),max(dummy) from dual ',dbms_sql.NATIVE);
dbms_sql.describe_columns(c, col_cnt, rec_tab);
for i in rec_tab.first..rec_tab.last loop
print_rec(rec_tab(i));
end loop;
dbms_sql.close_cursor(c);
END;
/(有关更多信息,请参见这里:sql.html)
OP还希望能够在查询中更改表的架构名称。我认为实现这一目标的最简单的方法是从user_tables查询表名,并在sql语句中搜索这些表名并对其进行前缀,或者执行'alter session set current_schema = ....'。
https://stackoverflow.com/questions/1614794
复制相似问题