利用dbms_metadata.get_ddl生成對應定義語句
這個話題不僅在網上已經被重複過不知道多少次了,在我的這個blog上也已
經是第二次來實現這個功能了。第一次的演算法比較土,就是找到指定的關鍵字
就換行,如:tablespace/storage等。這種方式很大的缺點就是如果是表定義
語句,而且是有很多欄位的(超過255字元數)的,就會出現錯誤。而且這個
錯誤還沒有很好的辦法來解決。
目前從dbms_metadata.get_ddl中獲取ddl語句最麻煩的就是如何在合適的
位置換行。如果一次輸出肯定會超出255的每行最大輸出字元數,會丟擲異常。
如果按照某個空格截斷,其實也很不好判斷到底在哪裡截。而且截出來的效
果100%的情況是非常差,也沒什麼可讀性了。
這次實現的方式應該說是靈機一動想出來的。也不用很多的步驟。
目前發現的除了對最大字元數有限制外(4000字元),其他都可正常使用。
我測試輸出了前面的254個字元,發現其實他本身的語句是有換行的。這就
給我提示。何不按他自己的換行符來實現分段擷取呢。
Oracle中的換行符可透過chr(10)來定位:
v_pos := instr(v_result, chr(10), i);
依次找到v_pos和之前的v_pos(v_tpos),就可以定位兩個換行符之間的一行了
if ( v_tpos <> v_pos ) then
v_temp := lower(substr(v_result, v_tpos, v_pos - v_tpos));
v_tpos := v_pos;
end if;
最新版本,支援超出4000字元範圍的大結構定義(如package等):
create or replace function w_func_getobjectddl_lob(
object_type varchar2,
object_name varchar2)
return tbl_varchar2 pipelined as
/*Created by
v_result varchar2(4000);
v_temp varchar2(2000);
v_pos pls_integer := 0;
v_tpos pls_integer := 0;
v_clob clob;
v_bufsize pls_integer := 4000;
v_cloblen pls_integer := 0;
v_nextpos pls_integer := 1;
v_prevpos pls_integer := 1;
v_initcount pls_integer := 50;
v_nextcount pls_integer := v_initcount;
v_offset pls_integer := 1;
begin
dbms_output.enable(9999999999999);
v_clob := dbms_metadata.get_ddl(object_type, object_name);
v_cloblen := dbms_lob.getlength(v_clob);
v_bufsize := dbms_lob.instr(v_clob, chr(10), 1, v_initcount);
while v_nextpos <> 0 loop
v_nextpos := dbms_lob.instr(v_clob, chr(10), 1, v_nextcount);
v_bufsize := (case when v_nextpos = 0 then v_cloblen else v_nextpos end) - v_prevpos;
dbms_lob.read(v_clob, v_bufsize, v_offset, v_result);
v_result := v_result || chr(10);
v_tpos := 0;
for j in 1..v_bufsize loop
v_pos := instr(v_result, chr(10), j);
if ( v_tpos <> v_pos ) then
v_temp := lower(substr(v_result, v_tpos + 1, v_pos - v_tpos - 1));
pipe row(v_temp);
v_tpos := v_pos;
end if;
end loop;
v_prevpos := v_nextpos;
v_offset := v_offset + v_bufsize;
v_nextcount := v_nextcount + v_initcount;
end loop;
return;
exception when others then
pipe row(sqlerrm);
return;
end w_func_getobjectddl_lob;
下面是實現的原始函式,透過管道來返回指定表的定義語句:
create or replace function w_func_getobjectddl(
object_type varchar2,
object_name varchar2)
return tbl_varchar2 pipelined as
/*Created by
v_result varchar2(4000);
v_temp varchar2(255);
v_pos pls_integer := 0;
v_tpos pls_integer := 0;
begin
dbms_output.enable(9999999999999);
v_result := dbms_metadata.get_ddl(object_type, object_name);
for i in 1..length(v_result) loop
v_pos := instr(v_result, chr(10), i);
if ( v_tpos <> v_pos ) then
v_temp := lower(substr(v_result, v_tpos, v_pos - v_tpos));
pipe row(v_temp);
v_tpos := v_pos;
end if;
end loop;
return;
end;
這裡需要有個陣列型別來支援管道的返回資訊:
create or replace type tbl_varchar2 as table of varchar2(255);
函式編譯成功後,即可透過下面的方式來獲取物件定義語句:
Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0
Connected as customer
SQL> select * from table(w_func_getobjectddl('TYPE', 'REC_INPUT_ASW'));
COLUMN_VALUE
--------------------------------------------------------------------------------
create or replace type "customer"."rec_input_asw" as object(
c_userinfoid varchar2(32),
c_answerid varchar2(32),
c_subjectid varchar2(32),
c_optionid varchar2(32),
c_continuation varchar2(1000) --答題內容
)
11 rows selected
SQL>
SQL> select * from table(w_func_getobjectddl('TABLE', 'TEST'));
COLUMN_VALUE
--------------------------------------------------------------------------------
create table "customer"."test"
( "name" varchar2(255),
"id" number(18,0)
) pctfree 10 pctused 40 initrans 1 maxtrans 255 nocompress logging
storage(initial 65536 next 1048576 minextents 1 maxextents 2147483645
6 rows selected
SQL>
後面考慮繼續最佳化這個函式功能。
下面又做了部分最佳化:
Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0
Connected as customer
SQL> select * from table(w_func_getobjectddl('TABLE', 'TEST'));
COLUMN_VALUE
--------------------------------------------------------------------------------
create table "customer"."test"
( "name" varchar2(255),
"id" number(18,0)
) pctfree 10 pctused 40 initrans 1 maxtrans 255 nocompress logging
storage(initial 65536 next 1048576 minextents 1 maxextents 2147483645
pctincrease 0 freelists 1 freelist groups 1 buffer_pool default)
tablespace "fund_table"
9 rows selected
SQL> select * from table(w_func_getobjectddl('TYPE', 'REC_INPUT_ASW'));
COLUMN_VALUE
--------------------------------------------------------------------------------
create or replace type "customer"."rec_input_asw" as object(
c_userinfoid varchar2(32),
c_answerid varchar2(32),
c_subjectid varchar2(32),
c_optionid varchar2(32),
c_continuation varchar2(1000) --答題內容
)
11 rows selected
SQL>
程式碼內容:
create or replace function w_func_getobjectddl(
object_type varchar2,
object_name varchar2)
return tbl_varchar2 pipelined as
/*Created by
v_result varchar2(4000);
v_temp varchar2(255);
v_pos pls_integer := 0;
v_tpos pls_integer := 0;
begin
dbms_output.enable(9999999999999);
v_result := dbms_metadata.get_ddl(object_type, object_name);
for i in 1..length(v_result) loop
v_pos := instr(v_result, chr(10), i);
if ( v_tpos <> v_pos ) then
prinfo('v_tpos: ' || v_tpos || ' -> v_pos: ' || v_pos);
v_temp := lower(substr(v_result, v_tpos + 1, v_pos - v_tpos - 1));
pipe row(v_temp);
v_tpos := v_pos;
end if;
end loop;
return;
end;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-607149/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用dbms_metadata.get_ddl檢視物件的定義語句。物件
- dbms_metadata.get_ddl()來獲得物件的定義語句物件
- oracle使用dbms_metadata.get_ddl包檢視DDL語句定義Oracle
- 利用dbms_metadata.get_ddl檢視DDL語句
- Oracle利用dbms_metadata.get_ddl檢視DDL語句Oracle
- informix SQL語句斷點定義ORMSQL斷點
- 定時生成分月表sql語句SQL
- mysql 還原表的定義語句MySql
- 用dbms_metadata.get_ddl獲取ddl語句
- 自定義註解例項實現SQL語句生成SQL
- 利用非對話語料來豐富對話生成模型模型
- 【轉義】使用SQL生成SQL語句時單引號的轉義處理SQL
- 對應定義結構獲取
- 使用SQL語句獲取SQLite中的表定義SQLite
- Java中如何解析SQL語句、格式化SQL語句、生成SQL語句?JavaSQL
- mybatis 得sql語句對應簡單型別MyBatisSQL型別
- dotnet C# 如何在頂級語句定義屬性C#
- 通過DBMS_METADATA.GET_DDL包獲得相關物件ddl語句物件
- 【轉義】使用SQL生成SQL語句時單引號的轉義處理之q'{}'方法SQL
- 利用SQL語句完成位操作 (轉)SQL
- SQL語句圖表生成工具ChartSQLSQL
- 找出消耗CPU最高的程式對應的SQL語句SQL
- IDEA自定義設定快捷鍵輸出你想要的語句!Idea
- 利用 JS 進行圖片處理並生成對應粒子圖JS
- MySQL利用索引優化ORDER BY排序語句MySql索引優化排序
- 利用迴圈語句隨機建立矩形隨機
- 利用 alter 語句修改欄位屬性
- mysql自定義排序順序語句MySql排序
- 三句義的程式語言
- mysql資料庫語句自動生成MySql資料庫
- jsqlparser使用記錄---生成sql語句JSSQL
- 根據DELTA自動生成SQL語句SQL
- python:利用iloc語句對列表的分類變數進行操作Python變數
- Flutter利用註解生成可自定義的路由Flutter路由
- 限定性定語從句和非限定性定語從句的區別
- 資料孤島的定義,企業如何應對?
- 軟體定義安全的發展及應對策略
- # 關於select關鍵字語句定義順序# 關於select關鍵字語句執行順序