* [[Oracleメモ]] - SQLメモ [#q8adc448]

#setlinebreak(on);

【DDLを取得する】
 SELECT DBMS_METADATA.GET_DDL('TABLE', 'テーブル名') FROM DUAL;
 SELECT DBMS_METADATA.GET_DDL('VIEW', 'ビュー名') FROM DUAL;
 SELECT DBMS_METADATA.GET_DDL('INDEX', '索引名') FROM DUAL;
 SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'トリガー名') FROM DUAL;
 など

【テーブルの列定義を確認する】
 SELECT * FROM USER_TAB_COLS WHERE TABLE_NAME = 'テーブル名';

【テーブルについている索引を確認する】
 SELECT * FROM USER_INDEXES_COLUMNS WHERE TABLE_NAME = 'テーブル名';
 SELECT * FROM USER_IND_COLUMNS WHERE TABLE_NAME = 'テーブル名' ORDER BY COLUMN_POSITION;

【文字コードから文字を取得】
 SELECT CHR(13) FROM DUAL; -- CR取得
 SELECT CHR(10) FROM DUAL; -- LF取得
 SELECT CHR(13) || CHR(10) FROM DUAL; -- CRLF取得
 /* UTL_FILEで PUTLINE でなく PUT を使用して改行コードを出力する場合は注意が必要!
    UTL_FILEはプラットフォームに依存する改行を出力するための文字としてLFを使用する様子。
    ファイルをRAWモードで開いていない限り、必ず末尾に改行が付いてしまうらしい。。
  */

【表領域のフルパスと自動拡張の設定値の確認】
 SELECT TABLESPACE_NAME,
        FILE_NAME,
        AUTOEXTENSIBLE
   FROM DBA_DATA_FILES
  WHERE TABLESPACE_NAME = '表領域名';

【表領域の空き容量の確認】
 SELECT SUM(BYTES) / 1024 || 'Kbytes' AS 空き領域サイズ
   FROM DBA_FREE_SPACE 
  WHERE TABLESPACE_NAME = '表領域名';

【連続する空き領域の結合】
 ALTER TABLESPACE APP COALESCE;

【インデックス再構築】
 ALTER INDEX インデックス名 REBUILD ONLINE;

【インデックス再構築方法(別のテーブルスペースに作成)】
 ALTER INDEX インデックス名 REBUILD TABLESPACE テーブルスペース名;

【データベース・バッファ・キャッシュを取得する】
 SET SERVEROUTPUT ON;
     DECLARE
       d_gets NUMBER;
       c_gets NUMBER;
       p_reads NUMBER;
       result NUMBER;
     BEGIN
       SELECT VALUE INTO d_gets FROM V$SYSSTAT
         WHERE NAME = 'db block gets';
       SELECT VALUE INTO c_gets FROM V$SYSSTAT 
         WHERE NAME = 'consistent gets';
       SELECT VALUE INTO p_reads FROM V$SYSSTAT 
         WHERE NAME = 'physical reads';
       result := 
         ROUND((1 - (p_reads / (c_gets + d_gets))),3) * 100;
       DBMS_OUTPUT.PUT_LINE(
         'データベース・バッファキャッシュヒット率->' ||
         result || '%');
     END;
     /
 ※一般的に、このヒット率が90%以上を維持できるようなデータベース・バッファ・キャッシュ・サイズを
  作成すべきとされている。
 ※ヒット率が90%に満たない場合は、初期化パラメータファイルのデータベース・バッファ・キャッシュのサイズを変更する。

【バッファ・キャッシュの空き比率を調べる】
 SET SERVEROUTPUT ON;
     DECLARE
       cnt_total NUMBER;
       cnt_free NUMBER;
       result NUMBER;
       message VARCHAR2(256);
     BEGIN
       SELECT COUNT(*) INTO cnt_total FROM X$BH;
       SELECT COUNT(*) INTO cnt_free FROM X$BH 
         WHERE STATE = 0;
       result := ROUND((cnt_free / cnt_total), 3) * 100;
       SELECT DECODE(SIGN(result), 1,
           'バッファキャッシュ余裕有り',
           'バッファキャッシュ余裕なし') INTO message
         FROM DUAL;
       DBMS_OUTPUT.PUT_LINE('バッファ空き比率->' || 
           result || '%');
       DBMS_OUTPUT.PUT_LINE(message);
     END;
     /

【共有プールのメモリサイズ情報を取得】
 SET SERVEROUTPUT ON;
     DECLARE
       sum_db_object_cache NUMBER;
       sum_s_sqlarea NUMBER;
       sum_u_sqlarea NUMBER;
       now_parameter NUMBER;
       result NUMBER;
     BEGIN
       SELECT SUM(SHARABLE_MEM) INTO sum_db_object_cache 
         FROM V$DB_OBJECT_CACHE;
       SELECT SUM(SHARABLE_MEM) INTO sum_s_sqlarea 
         FROM V$SQLAREA;
       SELECT SUM(250 * USERS_OPENING) INTO sum_u_sqlarea 
         FROM V$SQLAREA;
       result := 
         sum_db_object_cache + sum_s_sqlarea + sum_u_sqlarea;
       SELECT value INTO now_parameter 
         FROM V$PARAMETER WHERE NAME = 'shared_pool_size';
       DBMS_OUTPUT.PUT_LINE(
         'パラメータSHARED_POOL_SIZE->' || now_parameter);
       DBMS_OUTPUT.PUT_LINE(
         '現在最低限必要なSHARED_POOL_SIZE->' || result);
       DBMS_OUTPUT.PUT_LINE(
         '適正なSHARED_POOL_SIZE(×1.3)->' || result * 1.3);
     END;
     /

【ライブラリ・キャッシュ・ヒット率取得】
 SELECT SUM(PINS) AS キャッシュヒット合計,
        SUM(RELOADS) AS キャッシュミス合計,
        ROUND((1 - SUM(RELOADS) / SUM(PINS)) * 100, 2) || '%' AS ライブラリキャッシュヒット率
     FROM V$LIBRARYCACHE;

【ディクショナリヒット率の算出】
 SELECT SUM(GETS) AS キャッシュヒット合計,
        SUM(GETMISSES) AS キャッシュミス合計,
        ROUND((1 - SUM(GETMISSES) / SUM(GETS)) * 100, 2) || '%' AS ディクショナリヒット率
     FROM V$ROWCACHE;
 ※ヒット率は95%以上が望ましいとされています。

【初期化パラメータを参照する】
 SELECT NAME, VALUE FROM V$PARAMETER ORDER by NAME;

【DBの文字コードを調べる】
 select dump(col_name,1016) from table_name where rownum <= 1;
 /* col_name、table_nameは存在するものであれば何でもいい。
    col_nameはもちろん全角文字が入ってる列がよい。と思う。*/

【参照制約設定用のSQLを作るSQL】
 SET DEFINE ON
 SET LINESIZE 200
 SET SERVEROUTPUT ON SIZE 1000000
 DECLARE
    USER_NAME   VARCHAR2(20) DEFAULT 'ユーザID';
    CURSOR DISABLE_CSR IS  
           SELECT 'ALTER TABLE ' || A.TABLE_NAME || 
                  ' DISABLE CONSTRAINT "'  ||
                  A.CONSTRAINT_NAME || '";' "SQLTXT"
             FROM ALL_CONSTRAINTS A,
                  ALL_CONSTRAINTS B
            WHERE B.TABLE_NAME IN (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = USER_NAME)
              AND A.CONSTRAINT_TYPE   = 'R'
              AND A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME
           UNION
           SELECT 'ALTER TABLE ' || C.TABLE_NAME || 
                  ' DISABLE CONSTRAINT "'  ||
                  C.CONSTRAINT_NAME || '";'
             FROM ALL_CONSTRAINTS C
            WHERE C.TABLE_NAME IN (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = USER_NAME)
              AND C.CONSTRAINT_TYPE   = 'R'
         ORDER BY 1 ASC;
    CURSOR ENABLE_CSR IS  
           SELECT 'ALTER TABLE ' || A.TABLE_NAME || 
                  ' ENABLE VALIDATE CONSTRAINT "'  ||
                  A.CONSTRAINT_NAME || '";' "SQLTXT"
             FROM ALL_CONSTRAINTS A,
                  ALL_CONSTRAINTS B
            WHERE B.TABLE_NAME IN (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = USER_NAME)
              AND A.CONSTRAINT_TYPE   = 'R'
              AND A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME
           UNION
           SELECT 'ALTER TABLE ' || C.TABLE_NAME || 
                  ' ENABLE VALIDATE CONSTRAINT "'  ||
                  C.CONSTRAINT_NAME || '";'
             FROM ALL_CONSTRAINTS C
            WHERE C.TABLE_NAME IN (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = USER_NAME)
              AND C.CONSTRAINT_TYPE   = 'R'
         ORDER BY 1 ASC;
 BEGIN
    DBMS_OUTPUT.PUT_LINE('-- 参照制約無効化用SQL -- '); 
    FOR DISABLE_SQL IN DISABLE_CSR LOOP 
       DBMS_OUTPUT.PUT_LINE(DISABLE_SQL."SQLTXT"); 
    END LOOP; 
    DBMS_OUTPUT.PUT_LINE('-- 参照制約復活用SQL -- '); 
    FOR ENABLE_SQL IN ENABLE_CSR LOOP 
       DBMS_OUTPUT.PUT_LINE(ENABLE_SQL."SQLTXT"); 
    END LOOP; 
 END;
 /

【ユーザ権限の確認】
 select 'USER_ROLE_PRIVS' "PRIVILEGES",GRANTED_ROLE,ADMIN_OPTION,DEFAULT_ROLE,OS_GRANTED from USER_ROLE_PRIVS;
 select 'USER_SYS_PRIVS' "PRIVILEGES",PRIVILEGE,ADMIN_OPTION from USER_SYS_PRIVS;
 select OWNER || ' の ' || TABLE_NAME || ' を ' || PRIVILEGE || ' 可能' from USER_TAB_PRIVS where USER not like 'SYS%' and OWNER like 'SYS%';

【AUTOトレースのON】
 SET AUTOTRACE TRACEONLY

【実行計画の表示幅を変更】
 COLUMN plan_plus_exp format a60

【実行計画の調査】
 -- PLAN_TABLEを一旦削除
 delete from plan_table;

 -- 対象SQLの実行計画の取得
 explain plan
 set statement_id = '調査1' for 
 select * from ・・・・・・;

 -- 表示設定
 SET PAGESIZE 50
 SET LINESIZE 200
 COLUMN "QUERY PLAN" FORMAT A50
 COLUMN OBJECT_NEME  FORMAT A30

 -- 簡易表示
 SELECT LPAD(' ',2*(LEVEL-1))||OPERATION||' '||OPTIONS "QUERY PLAN" ,OBJECT_NAME
   FROM PLAN_TABLE 
  START WITH ID = 0
  CONNECT BY PRIOR ID = PARENT_ID
    AND STATEMENT_ID = '&STATEMENT_ID';

 -- ちょっと詳細表示
 set markup html preformat on
 select plan_table_output from table(dbms_xplan.display('plan_table',null,'serial'));

【統計情報の取得】
 BEGIN
   DBMS_STATS.GATHER_TABLE_STATS(
     OWNNAME       => 'USERID'
     ,TABNAME      => 'テーブル名'
     ,METHOD_OPT   => 'FOR ALL INDEXED'  -- 索引列のカラム統計を取る
     ,CASCADE      => TRUE               -- 関連する索引の統計も取る
   );
 END;
 /

【統計情報の削除】
 BEGIN
   DBMS_STATS.DELETE_TABLE_STATS('USERID','テーブル名');
 END;
 /

【ロックセッション抽出】
 /* ロックをかけているプログラム、ユーザの表示 */
 SELECT SADDR,SID,SERIAL#,USERNAME,PROGRAM
   FROM V$SESSION
  WHERE SID = ANY(SELECT SID FROM V$LOCK WHERE TYPE IN ('TX','TM'));

 /* 問題のSQLを表示 */
 SELECT A.SQL_TEXT,A.ADDRESS
   FROM V$SQLAREA A,V$SESSION B
  WHERE A.ADDRESS = B.SQL_ADDRESS
    AND B.SID = ANY(SELECT SID FROM V$LOCK WHERE TYPE IN ('TX','TM'));

 /* ロックをかけているセッションの情報を表示 */
 SELECT a.SID sid,
             a.USERNAME username,
             a.SERIAL# serialno,
             b.TYPE type,
             a.PROGRAM program,
             TO_CHAR(b.CTIME/60,'999990.9') lock_time,
             c.SQL_TEXT SQL
      FROM V$SESSION a,
           V$LOCK b,
           V$SQLAREA c
      WHERE a.SID = b.SID
        AND b.TYPE IN ('TX','TM')
        AND a.SQL_ADDRESS = c. ADDRESS;

 /*  ロックのため待ちが発生しているセッション情報 */
 SELECT a.USERNAME username,
             a.PROGRAM program,
             a.SERIAL# serialno,
             a.SID sid,
             b.TYPE type,
             TO_CHAR(b.CTIME/60,'999990.9') lock_time
      FROM V$SESSION a,
           V$LOCK b
      WHERE a.SID = b.SID
        AND b.TYPE = 'TM'
        AND b.SID = (SELECT SID FROM V$LOCK c WHERE c.TYPE = 'TX' AND c.REQUEST > 0);

 /* 問題のセッションをKILL ※SYSDBA権限が必要 */
 alter system kill session 'sid,serial'

** oracleセッションID取得 [#o438c36c]
 select userenv('SESSIONID') from dual

** SQLID取得(v$session) [#caea1664]
** SQL文取得(v$sqltext) [#xdc3da3a]
** SQLコスト取得(v$sqlarea) [#a4b64d6c]


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS