สคริปท์ Oracle DDL ในรูปแบบอัตโนมัติ


14

นักพัฒนา Oracle SQL สามารถส่งออก DDL ผ่านทางTools -> Database Export...นี้ทำงานได้ดีมาก แต่ต้องการการแทรกแซงด้วยตนเอง

ฉันรู้DBMS_METADATA.get_ddl()แต่พบว่าการส่งออกไม่สมบูรณ์ ฉันพบปัญหาที่DBMS_METADATADDL ที่ส่งออกไม่สามารถใช้งานได้โดยไม่ต้องแก้ไขปัญหาเช่นแบ่งในช่วงกลางของคำหลักและแย่กว่านั้น อย่างไรก็ตามหากใครรู้วิธีการส่งออก DDL ผ่านDMBS_METADATAสิ่งที่สามารถทำงานได้โดยไม่ต้องแก้ไขด้วยตนเองนั่นก็เป็นทางออกที่ดีเช่นกัน

โดยทั่วไปฉันกำลังมองหาวิธีอัตโนมัติ / สคริปต์เพื่อส่งออก DDL เหมือนกับสิ่งที่ส่งออกผ่านทางคู่มือ

ฉันจะทำสิ่งนั้นได้อย่างไร


1
คุณใช้ DBMS_METADATA ผ่าน SQLplus หรือไม่ คุณมีการตั้งค่าความกว้างบรรทัดของคุณ> 80 หรือไม่?
David Mann

ฉันใช้ SQLPlus มียูทิลิตี้ที่ดีขึ้นหรือไม่ คุณหมายถึง 'set linesize 200' หรือเปล่า ไม่สร้างความแตกต่างเลย
MatthewToday

2
ดูเหมือนว่าคนอื่นมีปัญหาเช่นกัน ข้อผิดพลาดใน Oracle เวอร์ชันก่อนหน้าและความยากในการทำให้ DBMS_METADATA เล่นได้ดีในรุ่นที่ใหม่กว่า asktom.oracle.com/pls/asktom/…โซลูชันของฉันไม่ดีสำหรับคุณ ฉันมักจะเรียกใช้ DBMS_METADATA ในเครื่องมือกราฟิก (เช่นคางคก) แล้วตัดและวางลงในเอกสารข้อความ ไม่แน่นอนโดยอัตโนมัติ แต่ดูเหมือนว่าจะจัดการกับจุดสิ้นสุดของบรรทัดด้วย CLOBs ที่ดีกว่า
David Mann

อืมมดูเหมือนว่าฉันอาจจะติดกับคู่มือวิธีสำหรับตอนนี้แล้ว ... ขอบคุณสำหรับความช่วยเหลือและการเชื่อมโยงแม้ว่า :)
MatthewToday

1
@David - คุณต้องตั้งค่าความกว้างคอลัมน์เอาท์พุทโดยใช้COLตามที่แสดงในตัวอย่างนี้และมันจะทำงาน
Nick Chammas

คำตอบ:


5

ถ้า sqlplus กำลังขันเอาต์พุต dbms_metadata.get_ddl ของคุณทำไมไม่เลือกเอาต์พุตใน CLOB และเขียน CLOB ไปยังระบบไฟล์

เช่น

DECLARE
    data CLOB;
    objType varchar2(30) := 'TABLE';
    objSchema varchar2(30) := 'SCOTT';
    objName varchar2(30) := 'EMP';
    fname varchar2(256) := objType || '_' || objSchema || '_' || objName || '.sql';
BEGIN
    SELECT dbms_metadata.get_ddl(objType,objName,objSchema) into data from dual;
    DBMS_XSLPROCESSOR.CLOB2FILE(data,'DATA_PUMP_DIR',fname);
END;
/

สิ่งนี้จะช่วยให้คุณแก้ไข DDL ได้โดยไม่เกิดความสับสน สิ่งเดียวคือสคริปต์จะถูกสร้างขึ้นบนเซิร์ฟเวอร์ DB และไม่ได้อยู่ในไคลเอนต์จากที่คุณเรียกใช้ sqlplus

สคริปต์ได้รับการบันทึกในไดเรกทอรีที่ชี้ไปที่รายการ 'DATA_PUPM_DIR' บนเซิร์ฟเวอร์ DB กล่าวคือ

select directory_path from all_directories where directory_name like 'DATA_PUMP_DIR';

ยิ่งไปกว่านั้นคุณสามารถเพิ่มการวนซ้ำของตาราง / ดัชนี ฯลฯ ทั้งหมดของ schema และรับ DDL ของ schema ที่สมบูรณ์ได้ในเวลาไม่นาน ฉันทำมันตลอดเวลา


2
หมายเหตุนี่เป็นการเขียนไฟล์ไปยังระบบไฟล์ของเซิร์ฟเวอร์ ใครก็ตามที่ต้องการรับ DDL บนเครื่องไคลเอนต์นี้จะไม่ประสบความสำเร็จ
Andrew Spencer

6

เหตุผลที่คุณมีปัญหาdbms_metadata.get_ddlคือมันส่งเอาต์พุตCLOBs ซึ่งมีขนาดสูงสุด 4GB โดยค่าเริ่มต้น SQL * Plus และ Oracle SQL Developer จะตัดข้อความยาวเพื่อไม่ให้ลูกค้าทิ้งขยะด้วยข้อความจำนวนมาก

มันง่ายมากที่จะลบล้างพฤติกรรมนี้ใน SQL * Plus ด้วยSETคำสั่งเล็กน้อยและรับ DDL ที่สะอาด

สคริปต์ที่คุณต้องการคือ:

-- Run this script in SQL*Plus.

-- don't print headers or other crap
set heading off;
set echo off;
set pagesize 0;      

-- don't truncate the line output
-- trim the extra space from linesize when spooling
set long 99999;      
set linesize 32767;  
set trimspool on;    

-- don't truncate this specific column's output
col object_ddl format A32000;

spool sys_ddl.sql;

SELECT dbms_metadata.get_ddl(object_type, object_name, owner) || ';' AS object_ddl
FROM DBA_OBJECTS
WHERE 
      OWNER = 'SYS'
  AND OBJECT_TYPE IN (
      'TABLE'
    , 'INDEX'
    , 'SEQUENCE'
    , 'VIEW'
  )
ORDER BY
    OWNER
  , OBJECT_TYPE
  , OBJECT_NAME
;

spool off;

0

การแปลงต่อไปนี้อาจช่วยได้ ฉันไม่ได้ใช้วิธีการ DBMS_XSLPROCESSOR.CLOB2FILE แต่ฉันใช้วิธีนี้เพื่อย้ายฐานข้อมูล Oracle จาก Solaris ไปเป็น Linux ฉันไม่สามารถใช้ปั๊มข้อมูลได้เนื่องจาก Oracle เวอร์ชันที่ใช้อยู่และความจริงที่ว่าพวกเขาใช้ชนิดข้อมูล XML สำหรับชนิดข้อมูลคอลัมน์

DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'PRETTY',             TRUE );
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR',      TRUE );
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'REF_CONSTRAINTS',    FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'OID',                FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE',         TRUE );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.