2021年3月31日 (水)

Difference of Initialization Parameters between 11gR2 (11.2.0.4.0) and 19c (19.3.0.0.0) - including hidden params

Previously on Mac De Oracle
19cの初期化パラメータ数や隠しパラメータ数などどう変化したのか、久々に確認してみた


ということで、今回はめでたくサポート終了となった11gR2と19cのパラメータ差分を確認してみた(何年振りだろうこれw)。21cがでたらまたやる予定。

11gR2 : 11.2.0.4.0
19c : 19.3.0.0.0

で比較した結果は以下

Difference of Initialization Parameters between 11gR2 (11.2.0.4.0) and 19c (19.3.0.0.0)



どうやればこの差分が作れるかというと、DBリンクでもできるけどそんなことしてません。というかやりたくないw ので、旧リリースでパラメータをcsv出力して(comma区切りではないですがw)、19c側で外部表として参照して差分を出力.

パラメータの取り出し。linesizeは適当に調整する必要はあるかも

ORACLE-ORCLCDB@SYS> !cat paramout.sql
set linesize 250
set trimspool on
set head off
set feedback off
set timi off
set termout off
set time off
set timi off
spo &1..csv

SELECT
TRIM(a.ksppinm)
||'|'||TRIM(a.ksppdesc)||'|'
FROM
x$ksppi a
/
spo off
undefine 1


上記スクリプトの実行、結果の例

ORACLE-ORCLCDB@SYS> @paramout 11.2.0.4.0_parameters
ORACLE-ORCLCDB@SYS> !cat 11.2.0.4.0_parameters.csv

_appqos_qt|System Queue time retrieval interval|
_ior_serialize_fault|inject fault in the ior serialize code|
_shutdown_completion_timeout_mins|minutes for shutdown operation to wait for sessions to complete|
_inject_startup_fault|inject fault in the startup code|
_latch_recovery_alignment|align latch recovery structures|
_spin_count|Amount to spin waiting for a latch|
_latch_miss_stat_sid|Sid of process for which to collect latch stats|
_max_sleep_holding_latch|max time to sleep while holding a latch|
_max_exponential_sleep|max sleep during exponential backoff|
_other_wait_threshold|threshold wait percentage for event wait class Other|
_other_wait_event_exclusion|exclude event names from _other_wait_threshold calculations|
・・・略・・・

外部表の元ネタであるファイル置き場用ディレクト作製とディレクトリオブジェクトの作製、そして、元ネタの配置は以下の通り

ORACLE-ORCLCDB@SYS> !pwd
/home/oracle
ORACLE-ORCLCDB@SYS> !ls -l exttab
合計 488
-rw-rw-r--. 1 oracle oracle 194319 3月 29 21:26 11.2.0.4_parameters.csv

ORACLE-ORCLCDB@SYS> CREATE DIRECTORY ext_tab AS '/home/oracle/exttab';

ディレクトリが作成されました。

ORACLE-ORCLCDB@SYS> l
1 CREATE TABLE ksppi_11_2_0_4_0 (
2 ksppinm VARCHAR2(80)
3 ,ksppdesc VARCHAR2(255)
4 )
5 ORGANIZATION EXTERNAL (
6 TYPE ORACLE_LOADER
7 DEFAULT DIRECTORY ext_tab
8 ACCESS PARAMETERS (
9 RECORDS DELIMITED BY NEWLINE
10 FIELDS TERMINATED BY '|'
11 (
12 ksppinm
13 ,ksppdesc
14 )
15 )
16 LOCATION (
17 '11.2.0.4_parameters.csv'
18 )
19* )
ORACLE-ORCLCDB@SYS> /

表が作成されました。

ORACLE-ORCLCDB@SYS> SELECT COUNT(1) FROM ksppi_11_2_0_4_0;

COUNT(1)
----------
2915


以下のスクリプトでcdb$rootのx$ksppiと前述の外部表をfull outer joinして差分をhtml形式で出力すればできあがり

col "11g R2 11.2.0.4.0" for a17
col "19c 19.3.0.0.0" for a17
set pagesize 10000
set timi off
set feed off
set markup html on spool on
spo param-diff.html
SELECT
CASE
WHEN prev.ksppinm = curr.ksppinm
OR (
prev.ksppinm IS NULL
AND curr.ksppinm IS NOT NULL
)
THEN curr.ksppinm
ELSE prev.ksppinm
END AS ksppinm
,CASE
WHEN prev.ksppinm = curr.ksppinm THEN '○'
WHEN prev.ksppinm IS NOT NULL AND curr.ksppinm IS NULL THEN '○'
ELSE 'n/a'
END AS "11g R2 11.2.0.4.0"
,CASE
WHEN prev.ksppinm = curr.ksppinm THEN '○'
WHEN prev.ksppinm IS NULL AND curr.ksppinm IS NOT NULL THEN '○'
ELSE 'n/a'
END AS "19c 19.3.0.0.0"
,CASE
WHEN prev.ksppdesc = curr.ksppdesc THEN curr.ksppdesc
WHEN prev.ksppinm IS NULL AND curr.ksppinm IS NOT NULL THEN curr.ksppdesc
WHEN prev.ksppinm iS NOT NULL AND curr.ksppinm IS NULL
THEN prev.ksppdesc
ELSE prev.ksppdesc
END AS kspdesc
,CASE
WHEN prev.ksppdesc = curr.ksppdesc
OR (prev.ksppinm IS NULL AND curr.ksppinm IS NOT NULL)
OR (prev.ksppinm IS NOT NULL AND curr.ksppinm IS NULL)
THEN NULL
ELSE curr.ksppdesc
END AS "New description"
FROM
(
SELECT * FROM x$ksppi WHERE con_id = 0
) curr
FULL OUTER JOIN ksppi_11_2_0_4_0 prev
ON
curr.ksppinm = prev.ksppinm
ORDER BY
1
;
spool off
set feed on
set set markup html off




露天風呂♨️行きたい...




Difference of Initialization Parameters between 11g r1 (11.1.0.6.0) and 12c r1 (12.1.0.1.0) - including hidden params
Difference of Initialization Parameters between 11g and 12c #2
19cの初期化パラメータ数や隠しパラメータ数などどう変化したのか、久々に確認してみた

| | コメント (0)

2021年3月22日 (月)

19cの初期化パラメータ数や隠しパラメータ数などどう変化したのか、久々に確認してみた


ORACLE-ORCLCDB@SYS> select banner_full from v$version;

BANNER_FULL
------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
compute sum label 'Total' of "Num Of Parameters" on report
break on report
WITH cte_params AS
(
SELECT
a.ksppinm
FROM
x$ksppi a JOIN x$ksppcv b
ON a.indx = b.indx
)
SELECT
*
FROM
(
SELECT
'1. Single underscore parameters' AS "CATEGORY"
, COUNT(1) AS "Num Of Parameters"
FROM
cte_params
WHERE
REGEXP_LIKE(ksppinm, '^([_][^_]){1}.*')
UNION
SELECT
'2. Double underscore parameters'
, COUNT(1)
FROM
cte_params
WHERE
REGEXP_LIKE(ksppinm, '^[_]{2}.*')
UNION
SELECT
'3. Non hidden parameters'
, COUNT(1)
FROM
cte_params
WHERE
REGEXP_LIKE(ksppinm, '^[^_].*')
)
ORDER by
category;

カウントした結果は以下のとおり。やはりhidden parameter、かなり増えてますよね。

CATEGORY                        Num Of Parameters
------------------------------- -----------------
1. Single underscore parameters 4934
2. Double underscore parameters 30
3. Non hidden parameters 448
-----------------
Total 5412

経過: 00:00:00.06

20210322-141656

 

ぽかぽか陽気すぎて、海辺でパタパタしたいw

 


Difference of Initialization Parameters between 11g r1 (11.1.0.6.0) and 12c r1 (12.1.0.1.0) - including hidden params
Difference of Initialization Parameters between 11g and 12c #2

 

| | コメント (0)

2021年2月13日 (土)

実行計画は、SQL文のレントゲン写真だ! No.30

OracleのResource Managerネタを書こう書こうと思いつつ類似ネタが他のブログでも扱われていることに気づきw
ネタを被らないようにしたいなぁとw 考えているうちにすでに2月の半ばw もうすこし考えまするw

ということで、今回はこないだ、実行計画という名のレントゲンネタに絡んだtwitterのやりとりがあったついでなので、INSERTの実行計画をいくつか追加しておきます。

Oracleもバージョンが上がるごとに実行計画の改善やオペレーション名を変えたりするので古いバージョンだと、そんなオペレーション出なーーーい。ということもありますが、そんなオペレーションがでたら、こんな意味なんだぁ。

と理解しておけば裏でどう動いているかイメージしやすいのではないかと思います。それがイメージできていれば、もし、性能問題に絡んでいた時にはどう対処するのが良いか、助けになるとはずです (^^)

DIRECT PATH LOADING登場前のOracle Databaseでは気にする必要はなかったのですが、DIRECT PATHが行われるようになってから実行計画のOperationでDIRECT PATHとの区別がつきやすいように追加されたという微かな記憶があります。
(まちがっていたらコメントいただけますと m(_ _)m

ということで、実行計画の見てみましょう。INSERT文なので単純ですw INSERTのoperationが(裏で)どう行われているかの違いです。
(以下の実行計画ではIASを利用して500MBほどの元表から同一定義の別表へ全データをINSERTしています)

LOAD TABLE CONVENTIONALというoperationが該当部分。 覚えておくと何かの役にはたつと思います!

20210213-150833

この実行計画になるように以下のようにNOAPPENDヒントでdirect path writeを抑止しています。ヒントの使い方も覚えておくとなにかのときにや役立ちますよ:)
NO_GATHER_OPTIMIZER_STATISTICSヒントは今回の実行計画には直接関係ないリアルタイム統計の取得を抑止するヒントです。
19cのおそらく後半のリリースから従来型のDMLでもリアルタイム統計が取得されるようになったようです。この例ではじゃまなので抑止。

従来型のDMLでもリアルタイム統計が取得される https://docs.oracle.com/cd/F19136_01/tgsql/optimizer-statistics-concepts.html#GUID-769E609D-0312-43A7-9581-3F3EACF10BA9

Real-Time Statistics https://docs.oracle.com/en/database/oracle/oracle-database/19/dblic/Licensing-Information.html#GUID-0F9EB85D-4610-4EDF-89C2-4916A0E7AC87

INSERT
/*+
MONITOR
NOAPPEND
NO_GATHER_OPTIMIZER_STATISTICS
*/
INTO
hoge2
SELECT
*
FROM
hoge
;

では、つづいて、direct path writeが動作した場合は該当部分のoperationはどうなるでしょうか? :)

LOAD AS SELECT に変わったoperationが該当部分です! operation は LOAD AS SELECT ですが、待機イベントは direct path write です。
どのようなoperationがどのような待機イベントに繋がるのかっていうのもおぼえておくと何かの役に立ちますよ ;)

20210213-150416

実行したINSERT文のヒントがNOAPPPENDからAPPENDに変えてあることに注目。この例ではdirect path writeをヒントで強制しています。

INSERT
/*+
MONITOR
APPEND
NO_GATHER_OPTIMIZER_STATISTICS
*/
INTO
hoge2
SELECT
*
FROM
hoge
;

最後に、NO_GATHER_OPTIMIZER_STATISTICS ヒントを外してリアルタイム統計取得が動いた場合にはどのようなoperationになるかみてみましょう。

20210213-153502

OPTIMIZER STATISTICS GATHERING というoperationが現れました。これは19cの後半で追加された従来型DMLでのリアルタイム統計取得が動作した場合も現れるとマニュアルに記載されているoperationとも同一です。
direct path writeなのかによらず、リアルタイム統計取得の動作有無を確認するためにはこのoperationの有無をチェックする必要があります!

INSERT
/*+
MONITOR
APPEND
*/
INTO
hoge2
SELECT
*
FROM
hoge
;

なかなかよい、レントゲンコレクションが撮れたな :)


Related article on Mac De Oracle
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 1 / TABLE FULL SCAN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 2 / INDEX UNIQUE SCAN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 3 / INDEX RANGE SCAN, Index Only Scan
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 4 / INDEX RANGE SCAN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 5 / INDEX RANGE SCAN, INLIST ITERATOR
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 6 / INDEX FAST SCAN, Index Only Scan
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 7 / INDEX FULL SCAN,Index Only Scan
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 8 / INDEX SKIP SCAN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 9 / TABLE ACCESS INMEMORY FULL
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 10 / NESTED LOOP JOIN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 11 / MERGE JOIN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 12 / HASH JOIN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 13 / HASH JOIN OUTER
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 14 / HASH JOIN FULL OUTER
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 15 / PX, TABLE ACCESS FULL
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 16 / CONCATENATION
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 17 / SORT UNIQUE, UNION-ALL = UNION
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 18 / UNION-ALL
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 19 / INTERSECTION
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 20 / MINUS
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 21 / WINDOW NOSORT STOPKEY
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 22 / COUNT STOPKEY
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 23 / HASH JOIN - LEFT-DEEP JOIN vs RIGHT-DEEP JOIN
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 24 / CONNECT BY NO FILTERING WITH START-WITH
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 25 / UNION ALL (RECURSIVE WITH) DEPTH FIRST, RECURSIVE WITH PUMP
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#1 / STAR TRANSFORM, VECTOR TRANSFORM (DWH向け)
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#2 / MERGE (UPSERT)
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#3 / RDFView
・実行計画は、SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#4 / INDEX FULL SCAN (MIN/MAX) - Index Only Scan

 

| | コメント (0)

2021年1月15日 (金)

SQL Macros / ほぼ理解した、つもり

SQL Macrosの使い道、ほぼ理解した:)

現在提供されている Live SQL 20.4.2(19c 19.8.0.0.0)で実行可能であることを確認<

Oracle DatabaseのSQLマクロを検証する
https://qiita.com/nakaie/items/75358c3138328dd985c4

SQL Macros - Creating parameterised views
https://livesql.oracle.com/apex/livesql/file/tutorial_KQNYERE8ZF07EZMRR6KJ0RNIR.html<

他のRDBMSからの移行では効果ありそうな気はするが、DWH系かなぁ。MySQLやPostgreSQLから移行してくるのは多くはなさそうだし。
その逆となると色々考え混むわけだが、新機能なのでそこまで影響なさそうな気もする。

昔関わったプロジェクトで、PL/SQL禁止されていた記憶はある。そのようなプロジェクトだと即、禁止されそうな機能ではあるが、単純にSQL文が内部展開されるのだとすると書き換えは容易にかもしれない。内部的にどうなるのか現物が出てきてたら詳しく見ておきたいところ。

個人的に、こいつの使い道は、既存UDFの高速化などがメインになるのかなと、遠ーくをみて妄想しているところ:)
特にデータ量が膨大になればなるほど此の手のが効いてくるわけで。

20210115-110329

| | コメント (0)

2019年12月30日 (月)

実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 おまけ#3

この実行計画がなにを行っているか見抜けたかたは, 前日のエントリーを読んだか, RDFVIEWを利用したRDF Graphを試したことがある方ぐらいだと思います.
RDF Semantic Graph「RDF 超入門」

RDFトリプルをRelational表にマップしてダイレクトにアクセスする方式なのですが, ご存じない方には何のこっちゃというのも仕方ないと思います.
3,4年前ぐらいに, なんとなーく流れ的に関わることになって, 寝る暇も惜しんでRDFトリプルストア (実態はオブジェクト表だったはず. 違ったらコメント頂けますと幸いです) とこのRDFVIEWのSQLチューニング方法を調べていたもんですw

そのころは余裕なさすぎてブログにも書けずじまいでしたが, 良い機会なのでRDFVIEWを問い合わせた実行計画をレントゲン写真として載せておきます.
詳細は前日の準備段階のエントリーを読んでいただけると良いかと思いますが, 知らない用語とかいきなりでてきているので, なんとなーくそんなもんかなーぐらいの理解よいと思います.

RDFVIEWのを問い合わせるSQL文は, SEM_MATCH()を利用するのが特徴で, RDFVIEW最大の特徴であるRelational表を直接よみながら, 最終的に RDFトリプルを返すという点にあります.
R2RML: RDB to RDF Mapping Language / W3Cあたりを読んでもらうと想像できるのではないかと思います. 読んで最初にきづくのは,それに関わっているのは Oracle社の方だったりしてるので納得感があります.

ということで、
SQLは以下のとおり. 関わったことがない方はこれまた見たこともない SEM_MATCH()関数が大量のパラメータを取って呼び出されていることが見えるぐらいですね。
裏では, SEM_MODEL()で指定したRDF Graphのモデルに対応したRelational表のEMPLOYEES表からEMPLOYEE_IDを元に, FIRST_NAME, LAST_NAME, MANAGER_IDの3列を, それぞれをトリプルとして返すようなマッピングになっています.

SELECT
s
, p
, o
FROM
TABLE (
SEM_MATCH (
'{?s ?p ?o}'
, SEM_MODELS('TEST_MODEL1')
, null
, null
, null
, null
, ' '
, null
, null
, 'RDFUSER'
, 'LOCALNET'
)
)
ORDER BY
s
,p;
RDFUSER@orcl> desc employees
Name Null? Type
----------------------------------------- -------- ----------------------------
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)

RDFUSER@orcl> break on index_name skip 1
RDFUSER@orcl> select index_name,column_name from user_ind_columns where table_name='EMPLOYEES' order by 1,2;

INDEX_NAME COLUMN_NAME
------------------------------ ------------------------------
EMP_DEPARTMENT_IX DEPARTMENT_ID

EMP_EMAIL_UK EMAIL

EMP_EMP_ID_PK EMPLOYEE_ID

EMP_JOB_IX JOB_ID

EMP_MANAGER_IX MANAGER_ID

EMP_NAME_IX FIRST_NAME
LAST_NAME

では, 実行計画を読み解いてみましょう.

EMPLOYEES表からEMPLOYEE_IDを元に, FIRST_NAME, LAST_NAME, MANAGER_IDの3列と説明しましたが, それぞれの列に索引が存在しているため, Index Only Scanで索引のみをアクセスし,
Id=7,8,9でEMPLOYEE_IDをEMP_EMP_ID_PK索引から, MANAGER_IDをEMP_MANAGER_IX索引から EMPLOYEE_IDとMANAGER_IDの2列からなら行を結合で作り出しています.
Id=11,12,13で同じく, EMPLOYEE_IDとEMP_NAME_IX索引から, EMPLOYEE_IDとLAST_NAMEの2列からなる行を結合で作り出してます.
Id=15,16,17でも, EMPLOYEE_IDとEM_NAME_IX索引から, EMPLOYEE_IDとFAST_NAMEの2列からなる行を結合でつくりだしています.

これらの動きから, トリプルを作成するために, EMPLOYEE_ID列, MANAGER_ID, FAST_NAME, FIRST_NAME列ぞれぞれを取得するために複数回索引にアクセスしています.
もし索引がなかったら, それぞれの列を取得するために, 複数回全表走査を行うだろうということは容易に想像できます. これらの動きは、RDFVIEWの特性の一つになっています. Relational表に格納されたデータを即刻RDFトリプルとして参照したいという目的のために性能にはある程度目をつぶっている姿が見えてきます.
列持ちのデータをトリプルという, ある意味, 行持ちのデータへ縦横変換しているわけですから仕方ない動作ではあります.

データの新鮮さよりも性能を, というケースでは, ロードという作業は必要になりますがトリプルストアを利用したほうが有利にはなります. トリプルストアをアクセスする実行計画は気が向いたら載せるかもしれません.
覚えておいてほしいことは, Id=19やPredicate InformationにRDF_RRのようなオブジェクトとUNION ALLのVIEWが1~3個登場したらRDFVIEWだろうということです. 治療が必要になった場合などには役にたつかもしれません.

Rdfview

-----
それでは, みなさま, 良いお年をお迎えください.



previously on Mac De Oracle
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 1 / TABLE FULL SCAN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 2 / INDEX UNIQUE SCAN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 3 / INDEX RANGE SCAN, Index Only Scan
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 4 / INDEX RANGE SCAN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 5 / INDEX RANGE SCAN, INLIST ITERATOR
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 6 / INDEX FAST SCAN, Index Only Scan
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 7 / INDEX FULL SCAN,Index Only Scan
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 8 / INDEX SKIP SCAN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 9 / TABLE ACCESS INMEMORY FULL
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 10 / NESTED LOOP JOIN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 11 / MERGE JOIN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 12 / HASH JOIN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 13 / HASH JOIN OUTER
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 14 / HASH JOIN FULL OUTER
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 15 / PX, TABLE ACCESS FULL
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 16 / CONCATENATION
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 17 / SORT UNIQUE, UNION-ALL = UNION
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 18 / UNION-ALL
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 19 / INTERSECTION
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 20 / MINUS
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 21 / WINDOW NOSORT STOPKEY
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 22 / COUNT STOPKEY
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 23 / HASH JOIN - LEFT-DEEP JOIN vs RIGHT-DEEP JOIN
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 24 / CONNECT BY NO FILTERING WITH START-WITH
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 25 / UNION ALL (RECURSIVE WITH) DEPTH FIRST, RECURSIVE WITH PUMP
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#1 / STAR TRANSFORM, VECTOR TRANSFORM (DWH向け)
・実行計画は,SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#2 / MERGE (UPSERT)

| | コメント (0)

2019年12月29日 (日)

RDFナレッジ・グラフ / 備忘録 19c

5年ぐらい前に触ったことがある程度で、すっかり忘れてしまった。しばらくぶりで思い出してパタパタしてみたら、Apache Jenaも含めていろいろ変わっていたので備忘録

RDFナレッジ・グラフ開発者ガイド RDFナレッジ・グラフの概要

R2RML: RDB to RDF Mapping Language

A Direct Mapping of Relational Data to RDF

いろいろ思い出しながら....

$ sqlplus sys@orclcdb as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Sat Dec 28 00:51:52 2019
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle. All rights reserved.

Enter password:

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> col namespace for a30
SQL> col value for a40
SQL> col description for a50
SQL> set linesize 400
SQL> set tab off
SYS@orclcdb> select * from MDSYS.RDF_PARAMETER;

NAMESPACE ATTRIBUTE VALUE DESCRIPTION
------------------- ----------------- ------------- --------------------------------------------------
COMPONENT RDFCTX INSTALLED Semantic (Text) Search component
COMPONENT RDFOLS INSTALLED RDF Optional component for OLS support
MDSYS SEM_VERSION 19.1.0.0.0 VALID

SYS@orclcdb> r
1 SELECT namespace, attribute, value FROM mdsys.rdf_parameter
2 WHERE namespace='MDSYS'
3 AND attribute IN ('FLOAT_DOUBLE_DECIMAL',
4 'XSD_TIME', 'XSD_BOOLEAN',
5* 'DATA_CONVERSION_CHECK')

no rows selected

SYS@orclcdb> conn system@orcl
Enter password:
Connected.
SYSTEM@orcl> create tablespace rdf_users datafile 'rds_users01.dbf' size 128m reuse autoextend on next 64m maxsize unlimited segment space management auto;

Tablespace created.

SYSTEM@orcl> create user rdfuser identified by hogehoge default tablespace rdf_users temporary tablespace temp;

User created.

SYSTEM@orcl> grant create view to rdfuser;

Grant succeeded.

SYSTEM@orcl> grant unlimited tablespace to rdfuser;

Grant succeeded.

SYSTEM@orcl> grant unlimited tablespace to mdsys;

Grant succeeded.

SYSTEM@orcl> grant select any dictionary to rdfuser;

Grant succeeded.

SYSTEM@orcl> grant connect, resource to rdfuser;

Grant succeeded.

SYSTEM@orcl> execute sem_apis.create_sem_network('RDF_USERS', network_owner=>'RDFUSER', network_name=>'LOCALNET');

PL/SQL procedure successfully completed.


SYSTEM@orcl> conn rdfuser@orcl
Enter password:
Connected.
RDFUSER@orcl>

RDFUSER@orcl> l
1 create table r2rmlview_nt_staging_tab (
2 rdf$stc_sub varchar2(4000) not null
3 ,rdf$stc_pred varchar2(4000) not null
4 ,rdf$stc_obj varchar2(4000) not null
5 )
6* nologging
RDFUSER@orcl> /

Table created.

RDFUSER@orcl> l
1 create table rdfview_export_tab (
2 rdf$stc_sub varchar2(4000) not null
3 ,rdf$stc_pred varchar2(4000) not null
4 ,rdf$stc_obj varchar2(4000) not null
5 )
6* nologging
RDFUSER@orcl> /

Table created.

RDFでいろいろやるには sga_targetやsga_max_sizeはそれなりに必要なので適当に調整

そして、Apache Jenaのrdfcatもdeprecatedになってて、これまたしばし時代に追いつく作業を....

RDFUSER@orcl> !rdfcat --help
------------------------------------------------------------------
DEPRECATED: Please use 'riot' instead.
http://jena.apache.org/documentation/io/#command-line-tools
------------------------------------------------------------------

------------------------------------
DEPRECATED: Please use riot instead.
------------------------------------

Usage: java jena.rdfcat (option|input)*
Concatenates the contents of zero or more input RDF documents.
Options: -out N3 | N-TRIPLE | RDF/XML | RDF/XML-ABBREV
-n expect subsequent inputs in N3 syntax
-x expect subsequent inputs in RDF/XML syntax
-t expect subsequent inputs in N-TRIPLE syntax
-[no]include include rdfs:seeAlso and owl:imports
input can be filename, URL, or - for stdin
Recognised aliases for -n are: -n3 -ttl or -N3
Recognised aliases for -x are: -xml -rdf or -rdfxml
Recognised aliases for -t are: -ntriple
Output format aliases: x, xml or rdf for RDF/XML, n, n3 or ttl for N3, t or ntriple for N-TRIPLE
See the Javadoc for jena.rdfcat for additional details.

rdfcatに変えて、riot ってやつをつかわなきゃいけなくなったっぽい。

RDFUSER@orcl> !riot -version
Jena: VERSION: 3.13.1
Jena: BUILD_DATE: 2019-10-06T18:57:39+0000
RIOT: VERSION: 3.13.1
RIOT: BUILD_DATE: 2019-10-06T18:57:39+0000

ちなみに、SHユーザのEMPLOYEES表や索引をRDFUSERユーザへコピーした上で、以下のような、RDFVIEWとRelational表と列のマッピングをTurtle (Terse RDF Triple Language)で定義した。

RDFUSER@orcl> !cat test_real_rdf_r2rml.ttl
@prefix rr: .
@prefix xsd: .
@prefix ex: .

ex:TriplesMap_Employees
rr:logicalTable [ rr:tableName "EMPLOYEES" ];
rr:subjectMap [
rr:template "http://r2rml.com/employees/{EMPLOYEE_ID}";
rr:class ex:Employees;
];

rr:predicateObjectMap [
rr:predicate ex:FirstName;
rr:objectMap [ rr:column "FIRST_NAME" ];
];

rr:predicateObjectMap [
rr:predicate ex:LastName;
rr:objectMap [ rr:column "LAST_NAME" ];
];

rr:predicateObjectMap [
rr:predicate ex:ManagerId;
rr:objectMap [ rr:column "MANAGER_ID" ];
].

5年ぐらい前の記憶ではrdfcatを利用して変換していたが、今は、 riot というコマンドを利用してTurtle(Terse RDF Triple Language)N-Triplesへ変換するみたいね。

RDFUSER@orcl> !riot --out=N-TRIPLE test_real_rdf_r2rml.ttl > test_real_rdf_r2rml_use_riot.nt

RDFUSER@orcl> !cat test_real_rdf_r2rml_use_riot.nt
_:Bf70c7f0d1b418dc63ad89dbcea313cd1 "EMPLOYEES" .
_:Bf70c7f0d1b418dc63ad89dbcea313cd1 .
_:Bdd4cf5eb9ecb0b12212d342518513827 "http://r2rml.com/employees/{EMPLOYEE_ID}" .
_:Bdd4cf5eb9ecb0b12212d342518513827 .
_:Bdd4cf5eb9ecb0b12212d342518513827 .
_:B310abfde7d61aac8f303fbd1f4ba5db8 .
_:Bfe48b8372e4da59d0ce99e0e24b894ad "FIRST_NAME" .
_:B310abfde7d61aac8f303fbd1f4ba5db8 _:Bfe48b8372e4da59d0ce99e0e24b894ad .
_:B310abfde7d61aac8f303fbd1f4ba5db8 .
_:B11c76919901c01b44cb0e2507a997c28 .
_:B5474fc7a1b7c7302521175dac3c58028 "LAST_NAME" .
_:B11c76919901c01b44cb0e2507a997c28 _:B5474fc7a1b7c7302521175dac3c58028 .
_:B11c76919901c01b44cb0e2507a997c28 .
_:Be7008cecff6b130ea15b4ba060cee0fb .
_:B0f41936e13c4655082ee47f866dc9f61 "MANAGER_ID" .
_:Be7008cecff6b130ea15b4ba060cee0fb _:B0f41936e13c4655082ee47f866dc9f61 .
_:Be7008cecff6b130ea15b4ba060cee0fb .


SQL*Loaderを使用したステージング表へのN-Triple形式のデータのロードを参考

RDFUSER@orcl> !cat test_real_rdf_r2rml_nt_load.ctl
UNRECOVERABLE
LOAD DATA
TRUNCATE
into table r2rmlview_nt_staging_tab
when (1) <> '#'
(
RDF$STC_sub CHAR(4000) terminated by whitespace
"(
CASE
WHEN substr(:RDF$STC_sub,1,1)='<' AND substr(:RDF$STC_sub,-1,1)='>' AND
length(:RDF$STC_sub)>2
THEN :RDF$STC_sub
WHEN substr(:RDF$STC_sub,1,2)='_:' AND
REGEXP_LIKE(:RDF$STC_sub,'^(_:)[[:alpha:]][[:alnum:]]*$')
THEN :RDF$STC_sub
WHEN substr(:RDF$STC_sub,1,1) NOT IN ('\"','<','#') AND
substr(:RDF$STC_sub,-1,1) NOT IN ('\"','>')
THEN ('<' || SDO_RDF.replace_rdf_prefix(:RDF$STC_sub) || '>')
WHEN substr(:RDF$STC_sub,1,1)='#'
THEN SDO_RDF.raise_parse_error(
'Ignored Comment Line starting with ', :RDF$STC_sub)
ELSE SDO_RDF.raise_parse_error('Invalid Subject', :RDF$STC_sub)
END
)",
RDF$STC_pred CHAR(4000) terminated by whitespace
"(
CASE
WHEN substr(:RDF$STC_pred,1,1)='<' AND substr(:RDF$STC_pred,-1,1)='>' AND
length(:RDF$STC_pred)>2
THEN :RDF$STC_pred
WHEN substr(:RDF$STC_pred,1,2) != '_:' AND
substr(:RDF$STC_pred,1,1) NOT IN ('\"','<') AND
substr(:RDF$STC_pred,-1,1) NOT IN ('\"','>')
THEN ('<' || SDO_RDF.replace_rdf_prefix(:RDF$STC_pred) || '>')
ELSE SDO_RDF.raise_parse_error('Invalid Predicate', :RDF$STC_pred)
END
)",
--
-- right-trimming of WHITESPACEs is reqd for "RDF$STC_obj"
-- (due to absence of "TERMINATED BY WHITESPACE")
--
-- For ease of editing below replace
-- "rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))" with ":xy".
-- and then replace back
--
RDF$STC_obj CHAR(4000)
"(
CASE
WHEN substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,1)='<' AND
substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),-1,1)='>' AND
length(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)))>2
THEN rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))
WHEN substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,1)='\"' AND
substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),-1,1)='\"' AND
length(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)))>1
THEN rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))
WHEN substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,2)='_:' AND
REGEXP_LIKE(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),
'^(_:)[[:alpha:]][[:alnum:]]*$')
THEN rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))
WHEN substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,1)
NOT IN ('\"','<') AND
substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),-1,1)
NOT IN ('\"','>')
THEN ('<' ||
SDO_RDF.replace_rdf_prefix(
rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))) ||
'>')
WHEN substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,1)='\"' AND
substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),-1,1)
NOT IN ('\"','>') AND
instr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),'\"\@',-1)>1 AND
REGEXP_LIKE(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),
'^\"[[:print:]]*\"\@[[:alpha:]]+(-[[:alnum:]]+)*$')
THEN rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13))
WHEN (substr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),1,1)='\"' AND
instr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),'\"^^',-1)>1 AND
(length(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)))-
(instr(rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)),'\"^^',-1)+4)
)>0)
THEN SDO_RDF.pov_typed_literal(
rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)))
ELSE SDO_RDF.raise_parse_error(
'Invalid Object', rtrim(:RDF$STC_obj,'. '||CHR(9)||CHR(10)||CHR(13)))
END
)"
)

RDFUSER@orcl> exit


$ sqlldr userid=rdfuser@orcl control=test_real_rdf_r2rml_nt_load.ctl data=test_real_rdf_r2rml_use_riot.nt direct=true skip=0 load=1000000 discardmax=0 bad=test_real_rdf_r2rml_nt_load.bad discard=test_real_rdf_r2rml_nt_load.rej log=test_real_rdf_r2rml_nt_load.log errors=1000000
Password:

SQL*Loader: Release 19.0.0.0.0 - Production on Sat Dec 28 02:05:44 2019
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.

Path used: Direct, LOAD=1000000

Load completed - logical record count 17.

Table R2RMLVIEW_NT_STAGING_TAB:
17 Rows successfully loaded.

Check the log file:
test_real_rdf_r2rml_nt_load.log
for more information about the load.

そして、SEM_MATCH()関数を利用してモデルと問い合わせると....

RDFUSER@orcl> @test_real_rdf_cre_rdfview.sql

PL/SQL procedure successfully completed.

RDFUSER@orcl> l
1 SELECT
2 s
3 , p
4 , o
5 FROM
6 TABLE (
7 SEM_MATCH (
8 '{?s ?p ?o}'
9 , SEM_MODELS('TEST_MODEL1')
10 , null
11 , null
12 , null
13 , null
14 , ' '
15 , null
16 , null
17 , 'RDFUSER'
18 , 'LOCALNET'
19 )
20 )
21 ORDER BY
22 s
23 ,p
24*
RDFUSER@orcl>
RDFUSER@orcl> @test_query_rdfview.sql

S P O
---------------------------------------- -------------------------------------------------- ----------------------------------------
http://r2rml.com/employees/100 http://r2rml.com/ns#FirstName Steven
http://r2rml.com/employees/100 http://r2rml.com/ns#LastName King
http://r2rml.com/employees/100 http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://r2rml.com/ns#Employees
http://r2rml.com/employees/101 http://r2rml.com/ns#FirstName Neena
http://r2rml.com/employees/101 http://r2rml.com/ns#LastName Kochhar
http://r2rml.com/employees/101 http://r2rml.com/ns#ManagerId 100
http://r2rml.com/employees/101 http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://r2rml.com/ns#Employees
http://r2rml.com/employees/102 http://r2rml.com/ns#FirstName Lex
http://r2rml.com/employees/102 http://r2rml.com/ns#LastName De Haan
http://r2rml.com/employees/102 http://r2rml.com/ns#ManagerId 100

・・・中略・・・

http://r2rml.com/employees/205 http://r2rml.com/ns#FirstName Shelley
http://r2rml.com/employees/205 http://r2rml.com/ns#LastName Higgins
http://r2rml.com/employees/205 http://r2rml.com/ns#ManagerId 101
http://r2rml.com/employees/205 http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://r2rml.com/ns#Employees
http://r2rml.com/employees/206 http://r2rml.com/ns#FirstName William
http://r2rml.com/employees/206 http://r2rml.com/ns#LastName Gietz
http://r2rml.com/employees/206 http://r2rml.com/ns#ManagerId 205
http://r2rml.com/employees/206 http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://r2rml.com/ns#Employees

| | コメント (0)

2019年9月30日 (月)

なぜ、そこに、LONG型があるんだ / FAQ

all/dba/user_tab_columns

https://docs.oracle.com/cd/E82638_01/refrn/ALL_TAB_COLUMNS.html#GUID-F218205C-7D76-4A83-8691-BFD2AD372B63

これらのビューは、列の属性関連の情報を持つビューです。
たまに、便利なびゅーではあるのですが、これらのビューをアクセスする使うスクリプトというかPL/SQLでコード書くこともあるのですが、一箇所だけ、使いにくいところがあります。

 

どこかわかります?

下位互換のためだろうと思われるのですが、一般には推奨されていない LONG型の列 が残っています。

ご存知だとは思いますが、一般的なガイドだと、CLOBの利用が推奨されています。
下位互換のためだから仕方ないのだとは思うのですが。

LONG型といえば、とにかく制約が多くて、文字列操作を行うにもめんどくさいわけで、実際に利用したい状況になると、うううううっとなることしばしば。

LONG型

で、普段どうやって、その面倒くさいところを回避しているかといえば、CLOBに変換してしまうことがが多いです。
CLOBにしてしまえば、沢山の制約から解放されますしね :)

以下のような感じで。


SCOTT> l
1 CREATE TABLE my_dba_tab_columns
2 AS
3 SELECT
4 owner
5 ,table_name
6 ,column_name
7 ,data_type
8 ,data_type_mod
9 ,data_type_owner
10 ,data_length
11 ,data_precision
12 ,data_scale
13 ,nullable
14 ,column_id
15 ,TO_CLOB(default_length) AS default_length
16 ,num_distinct
17 ,low_value
18 ,high_value
19 ,density
20 ,num_nulls
21 ,num_buckets
22 ,last_analyzed
23 ,sample_size
24 ,character_set_name
25 ,char_col_decl_length
26 ,global_stats
27 ,user_stats
28 ,avg_col_len
29 ,char_length
30 ,char_used
31 ,v80_fmt_image
32 ,data_upgraded
33 ,histogram
34 ,default_on_null
35 ,identity_column
36 ,sensitive_column
37 ,evaluation_edition
38 ,unusable_before
39 ,unusable_beginning
40 ,collation
41 FROM
42* dba_tab_columns
SCOTT> /

Table created.

SCOTT> desc dba_tab_columns
Name Null? Type
----------------------------------------- -------- ----------------------------
OWNER NOT NULL VARCHAR2(128)
TABLE_NAME NOT NULL VARCHAR2(128)
COLUMN_NAME NOT NULL VARCHAR2(128)
DATA_TYPE VARCHAR2(128)
DATA_TYPE_MOD VARCHAR2(3)
DATA_TYPE_OWNER VARCHAR2(128)
DATA_LENGTH NOT NULL NUMBER
DATA_PRECISION NUMBER
DATA_SCALE NUMBER
NULLABLE VARCHAR2(1)
COLUMN_ID NUMBER
DEFAULT_LENGTH NUMBER
DATA_DEFAULT LONG
NUM_DISTINCT NUMBER
LOW_VALUE RAW(2000)
HIGH_VALUE RAW(2000)
DENSITY NUMBER
NUM_NULLS NUMBER
NUM_BUCKETS NUMBER
LAST_ANALYZED DATE
SAMPLE_SIZE NUMBER
CHARACTER_SET_NAME VARCHAR2(44)
CHAR_COL_DECL_LENGTH NUMBER
GLOBAL_STATS VARCHAR2(3)
USER_STATS VARCHAR2(3)
AVG_COL_LEN NUMBER
CHAR_LENGTH NUMBER
CHAR_USED VARCHAR2(1)
V80_FMT_IMAGE VARCHAR2(3)
DATA_UPGRADED VARCHAR2(3)
HISTOGRAM VARCHAR2(15)
DEFAULT_ON_NULL VARCHAR2(3)
IDENTITY_COLUMN VARCHAR2(3)
SENSITIVE_COLUMN VARCHAR2(3)
EVALUATION_EDITION VARCHAR2(128)
UNUSABLE_BEFORE VARCHAR2(128)
UNUSABLE_BEGINNING VARCHAR2(128)
COLLATION VARCHAR2(100)

SCOTT> desc my_dba_tab_columns
Name Null? Type
----------------------------------------- -------- ----------------------------
OWNER NOT NULL VARCHAR2(128)
TABLE_NAME NOT NULL VARCHAR2(128)
COLUMN_NAME NOT NULL VARCHAR2(128)
DATA_TYPE VARCHAR2(128)
DATA_TYPE_MOD VARCHAR2(3)
DATA_TYPE_OWNER VARCHAR2(128)
DATA_LENGTH NOT NULL NUMBER
DATA_PRECISION NUMBER
DATA_SCALE NUMBER
NULLABLE VARCHAR2(1)
COLUMN_ID NUMBER
DEFAULT_LENGTH CLOB
NUM_DISTINCT NUMBER
LOW_VALUE RAW(2000)
HIGH_VALUE RAW(2000)
DENSITY NUMBER
NUM_NULLS NUMBER
NUM_BUCKETS NUMBER
LAST_ANALYZED DATE
SAMPLE_SIZE NUMBER
CHARACTER_SET_NAME VARCHAR2(44)
CHAR_COL_DECL_LENGTH NUMBER
GLOBAL_STATS VARCHAR2(3)
USER_STATS VARCHAR2(3)
AVG_COL_LEN NUMBER
CHAR_LENGTH NUMBER
CHAR_USED VARCHAR2(1)
V80_FMT_IMAGE VARCHAR2(3)
DATA_UPGRADED VARCHAR2(3)
HISTOGRAM VARCHAR2(15)
DEFAULT_ON_NULL VARCHAR2(3)
IDENTITY_COLUMN VARCHAR2(3)
SENSITIVE_COLUMN VARCHAR2(3)
EVALUATION_EDITION VARCHAR2(128)
UNUSABLE_BEFORE VARCHAR2(128)
UNUSABLE_BEGINNING VARCHAR2(128)
COLLATION VARCHAR2(100)

 


db tech showcase 2019もおわり、今年も残すところ 3ヶ月あまり。一年早い. そして。
来週は、開催時期を秋に変更してから2回目の多摩川花火大会。天気がよいといいのですが:)

ではまた。

| | コメント (0)

2019年8月25日 (日)

FAQ / PL/SQL PACKAGEでパプリックスコープを持つ定数をSQL文中で利用するには...

かなーり、ご無沙汰しておりました。(本業でいっぱいいっぱいで、という言い訳はこれぐらいにしてw) 偶に聞かれることがあるので、FAQネタから。 パッケージでパブリックなスコープを持つ定数は無名PL/SQLブロックやパッケージ、プロシージャ、ファンクションでしか参照できないんですよねー 例えば、DBMS_CRYPTOパッケージでHASHファンクションを利用してSH-256を作成したいなーと思って、

39.4 DBMS_CRYPTOのアルゴリズム
https://docs.oracle.com/cd/F19136_01/arpls/DBMS_CRYPTO.html#GUID-CE3CF17D-E781-47CB-AEE7-19A9B2BCD3EC
DBMS_CRYPTO.HASH()は関数なのでSQL文から呼びたーい、と以下のような使い方をすると...

SQL> SELECT DBMS_CRYPTO.HASH(TO_CLOB('hoge'), DBMS_CRYPTO.HASH_SH2569) AS "SH-256" FROM dual;
SELECT DBMS_CRYPTO.HASH(TO_CLOB('hoge'), DBMS_CRYPTO.HASH_SH2569) AS "SH-256" FROM dual
*
ERROR at line 1:
ORA-00904: "DBMS_CRYPTO"."HASH_SH2569": invalid identifier


SQL>
SQL> select DBMS_CRYPTO.HASH_SH256 from dual;
select DBMS_CRYPTO.HASH_SH256 from dual
*
ERROR at line 1:
ORA-06553: PLS-221: 'HASH_SH256' is not a procedure or is undefined
見事にエラーとなるわけです。 DBMS_CRYPTO.HASH_SH256は、パッケージファンクションではないので...利用可能なのはPL/SQLでのみ。
SQL> set serveroutput on
SQL>
¥SQL>
SQL> begin
2 dbms_output.put_line('DBMS_CRYPTO.HASH_SH256 : ' || DBMS_CRYPTO.HASH_SH256);
3 end;
4 /
DBMS_CRYPTO.HASH_SH256 : 4

PL/SQL procedure successfully completed.
SQL文で活用する為には、ファンクションでラップする必要があります。 以下のように。
SQL> l
1 CREATE OR REPLACE FUNCTION get_hash_sh256_type
2 RETURN NUMBER
3 AS
4 BEGIN
5 RETURN DBMS_CRYPTO.HASH_SH256;
6* END;
SQL> /

Function created.

SQL>
冒頭でエラーとなっていたSQL文をDBMS_CRYPTO.HASH_SH256を返すファンクションを使うように書き換えると、 はい、できました。
SQL> l
1 SELECT
2 DBMS_CRYPTO.HASH(
3 TO_CLOB('hoge')
4 , get_hash_sh256_type()
5 ) AS "SH-256"
6 FROM
7* dual
SQL> /

SH-256
--------------------------------------------------------------------------------
ECB666D778725EC97307044D642BF4D160AABB76F56C0069C71EA25B1E926825

SQL>


露店の焼きそばと焼き鳥を食べつつ、晩夏の夏祭りと、涼しい朝晩の気温で熟睡可能な山形より。 では、では。

| | コメント (0)