pl/sql最新情報 -...

44
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | PL/SQL最新情報 日本オラクル株式会社 ソリューション・エンジニアリング統括 クラウド・インフラストラクチャー本部 中家 裕之 2019/02/21 Oracle Database Technology Night

Upload: others

Post on 12-Sep-2019

0 views

Category:

Documents


0 download

TRANSCRIPT

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQL最新情報

日本オラクル株式会社ソリューション・エンジニアリング統括クラウド・インフラストラクチャー本部中家 裕之

2019/02/21

Oracle Database Technology Night

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

•以下の事項は、弊社の一般的な製品の方向性に関する概要を説明するものです。また、情報提供を唯一の目的とするものであり、いかなる契約にも組み込むことはできません。以下の事項は、マテリアルやコード、機能を提供することをコミットメント(確約)するものではないため、購買決定を行う際の判断材料になさらないで下さい。オラクル製品に関して記載されている機能の開発、リリースおよび時期については、弊社の裁量により決定されます。

Oracle と Java は、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における登録商標です。文中の社名、商品名等は各社の商標または登録商標である場合があります。

2

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

アジェンダ

3

1

2

3

More Faster!!- パフォーマンス向上のための新機能PickUp

More Convenient!!- パフォーマンス以外のPL/SQL新機能PickUp

More Powerful!!- PL/SQLの開発生産性向上

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

本章で解説する機能

• ネイティブ・コンパイル

• PL/SQL特有の数値型

•順序の取得方法の変更

• PL/SQLファンクション結果キャッシュ

• DBMS_PARALLEL_EXECUTE

4

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

ネイティブ・コンパイル

•標準ではPL/SQLは中間コードにコンパイルされる

• Oracle9i以降、ネイティブ・コンパイル機能が追加–中間コードではなく、C言語の実行モジュールの形式にコンパイルすることで、

PL/SQLの処理を高速化

–ただしコンパイラを別途用意する必要があった

• 11gよりコンパイラの追加が不要となった

•設定方法:初期化パラメータPLSQL_CODE_TYPEを「NATIVE」に設定–デフォルトは「INTERPRETED」(中間コードにコンパイル)

5

11gからコンパイラ追加が不要に!!

11gR1~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQL特有の数値型

• NUMBER型のようなテーブルのデータ型としては指定不可→PL/SQL内の変数のデータ型として利用– 12.1より、引数にこのようなデータ型を使用しても、SQLから呼び出せるようになった

•指定精度は整数

• NUMBER型を使用する場合に比べ、以下のメリットがある–メモリ消費が少ない

–演算速度が速い

6

特徴とメリット

PL/SQL内で使用する整数の変数のデータ型として最適!!

11gR1~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQL特有の数値型

7

データ型の名称 サイズ 値の範囲 オーバーフローのチェック

NOT NULL制約

PLS_INTEGER(BINARY_INTEGER) 4バイト

-2147483648から2147483647の整数

あり なし

SIMPLE_INTEGER なし あり

• 11g以降、PLS_INTEGERとBINARY_INTEGERは同じ実装– SIMPLE_INTEGERもPLS_INTEGERのサブタイプ

• 11gより追加されたSIMPLE_INTEGERは、 PLS_INTEGERより高速–オーバーフローのチェックがない分高速

–NOT NULL制約が付与されるので注意

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

順序の取得方法の変更

• 10g以前:SELECT文で取得する必要あり

• 11g以降:PL/SQLの式として順序が利用可能–旧方式も引き続きサポートされる

–旧方式よりも高速に実行される

8

11gR1~

DECLAREval PLS_INTEGER;

BEGINSELECT SEQ_TECHNIGHT.NEXTVALINTO val FROM DUAL;

END;

DECLAREval PLS_INTEGER;

BEGINval := SEQ_TECHNIGHT.NEXTVAL;

END;

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQLファンクション結果キャッシュ

• ファンクションの結果をSGAの専用領域にキャッシング– SQLの結果キャッシュと同じ領域を使用

•結果キャッシュにデータが存在する場合は処理を実行せず、処理結果を即座に返却→同じ処理結果になることが多いファンクションがキャッシング対象

• テーブルデータを読んでいるファンクションの場合、テーブルの更新により結果が変わる場合、該当のキャッシュが自動で破棄される– 11gR1では更新を検知すべきテーブルを指定する必要あり。11gR2以降は自動検出

– SYSDATEやSYS_GUIDにような、テーブルを参照せずにコールの度に結果が変わるような関数の結果をキャッシングした場合、更新されず誤った値が返るので注意

9

概要

11gR1~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQLファンクション結果キャッシュ

10

初期化パラメータ

RESULT_CACHE_MODE

•MANUAL(デフォルト):ヒント句などで明示的にキャッシュする指定をしたものだけがキャッシング対象

• FORCE:すべてが強制的にキャッシングされる

RESULT_CACHE_REMOTE_EXPIRATION

• リモート・オブジェクトを使用する結果が有効なまま維持される時間(分)

• デフォルトは0でキャッシュを行わない

RESULT_CACHE_MAX_SIZE

• SGA内の結果キャッシュのサイズ

•デフォルト値は他の初期化パラメータから導出

• 0にすると結果キャッシュが無効化される

RESULT_CACHE_MAX_RESULT

•一つの結果が結果キャッシュを使用してもよい最大の割合

•デフォルトは5(%)

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQLファンクション結果キャッシュ

11

サンプルコーディングと実行例

CREATE OR REPLACE FUNCTION sample (n NUMBER)RETURN NUMBER RESULT_CACHE IS

BEGINDBMS_SESSION.SLEEP(10);RETURN n * 2;

END;

SQL> select sample(5) from dual;

SAMPLE(5)----------

10

経過: 00:00:10.06SQL> /

SAMPLE(5)----------

10

経過: 00:00:00.02

サンプルコーディング 実行例

RESULT_CACHE_MODEがMANUALの場合、この指定をしないと結果キャッシュが生成されない故意に処理時間を要する

コーディングを行い、結果キャッシュの効果を確認

結果キャッシュを利用しているため、10秒の待機を行っていない

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

DBMS_PARALLEL_EXECUTE

• テーブルの更新を行うストアド・プロシージャを多重実行するパッケージ

• Enterprise EditionのパラレルDMLとは異なる

• Standard Editionでも利用可

•自前でバッチジョブを多重化して実行するよりも、はるかに簡便

12

概要とメリット

自前で多重化

ストアドJOB 1

ストアドJOB 2

ストアドJOB 3

• 並列度分のジョブ登録が必要

• 並列度を変える場合、ジョブ構成の変更が必要

先行JOB

ストアドJOB

先行JOB

DBMS_PARALLEL_EXECUTE

• ジョブ登録は一つでOK

• 並列度の変更をジョブ構成変更ではなく、引数の変更やプログラミングロジック(例:処理件数に応じて変動)で対応することが可能

11gR2~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

DBMS_PARALLEL_EXECUTE

並列更新タスクの作成

(DBMS_PARALLEL_EXECUTE.CREATE_TASK)

タスクの分割方法(並列度)を指定

(DBMS_PARALLEL_EXECUTE. CREATE_CHUNKS_BY_ROWID等)

タスクを実行

(DBMS_PARALLEL_EXECUTE.RUN_TASK)

タスクを終了

(DBMS_PARALLEL_EXECUTE.DROP_TASK)

13

基本的な処理(コーディング)の流れ

分割方式により、呼び出すプロシージャが異なる(後述)

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

DBMS_PARALLEL_EXECUTE

• DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID

– ROWIDをベースに分割

• DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL

–分割単位を返却するSQLの結果を以て分割

–例:部門番号を返却するSQLを指定し、部門番号単位に分割SELECT DISTINCT DEPT_NO FROM DEPT

• DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_NUMBER_COL

–指定した並列度で分割

–引数にNUMBER型の列を指定する必要がある

• 分割方式を自前ロジックにすることも可能

14

処理の分割(チャンク)単位:いずれかを使用

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

DBMS_PARALLEL_EXECUTE

15

サンプルコーディング(ROWIDをベースに分割)DECLARE

l_sql_stmt VARCHAR2(1000) := 'update EMPLOYEES e SET e.salary = e.salary + 10WHERE rowid BETWEEN :start_id AND :end_id';

l_try NUMBER := 0;l_status NUMBER;

BEGINDBMS_PARALLEL_EXECUTE.CREATE_TASK ('mytask');DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID('mytask', 'HR', 'EMPLOYEES', true, 100);DBMS_PARALLEL_EXECUTE.RUN_TASK('mytask', l_sql_stmt, DBMS_SQL.NATIVE, parallel_level => 10);L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');WHILE(l_try < 2 and L_status != DBMS_PARALLEL_EXECUTE.FINISHED) LOOP

L_try := l_try + 1;DBMS_PARALLEL_EXECUTE.RESUME_TASK('mytask');L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');

END LOOP;DBMS_PARALLEL_EXECUTE.DROP_TASK('mytask');

END;

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

アジェンダ

16

2

3

More Faster!!- パフォーマンス向上のための新機能PickUp

More Convenient!!- パフォーマンス以外のPL/SQL新機能PickUp

More Powerful!!- PL/SQLの開発生産性向上

1

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

本章で解説する機能

•暗黙的SQL文結果セット

• DBMS_SESSION.SLEEP

•多相テーブルファンクション

•修飾式の追加

• プライベート一時表

17

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

暗黙的SQL文結果セット

• 11gまでは、SELECTのストアドはREF CURSORのOUTパラメータが必要→他のRDBMSのストアドでは不要→移植性を高めるため、12cより他RDBMS同様の対応が可能に

18

SELECTのストアドプロシージャ呼び出しのコーディングの簡素化

CREATE OR REPLACE PROCEDURE SAMPLE(RS OUT SYS_REFCURSOR) ISBEGIN

OPEN RS FOR SELECT DNAME FROM DEPT;END;

CREATE OR REPLACE PROCEDURE SAMPLE ISRS SYS_REFCURSOR;

BEGINOPEN RS FOR SELECT DNAME FROM DEPT;DBMS_SQL.RETURN_RESULT(RS);

END;

11g以前 12c以降

12gR1~

OUTの引数不要

要追加

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

暗黙的SQL文結果セット

19

SQL*Plusでのプロシージャ実行例

SQL> var cur refcursorSQL> exec sample(:cur)

PL/SQLプロシージャが正常に完了しました。

SQL> print cur

DNAME----------------------------ACCOUNTINGRESEARCHSALESOPERATIONS

SQL> exec sample

PL/SQLプロシージャが正常に完了しました。

ResultSet #1

DNAME----------------------------ACCOUNTINGRESEARCHSALESOPERATIONS

11g以前 12c以降

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

暗黙的SQL文結果セット

20

Javaでのプロシージャ呼び出し例(抜粋)

cstmt = conn.prepareCall ("call sample(?);"); cstmt.registerOutParameter(1,OracleTypes.CURSOR);cstmt.execute();ResultSet cursor =

((OracleCallableStatement)cstmt).getCursor(1); while (cursor.next ())

{System.out.println (cursor.getString(1));}

cstmt = conn.prepareCall ("call sample;"); cstmt.execute();ResultSet cursor = cstmt.getResultSet();while (cursor.next ())

{System.out.println (cursor.getString(1));}

11g以前 12c以降

SELECT文と同様のコーディング独自のコーディング

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

暗黙的SQL文結果セット

• アプリケーションソースとSQL文の分離が可能– SQL文の修正に呼び出し元アプリケーションの修正が不要• SQL文自体の書き換え

• ヒント句のチューニングの追加

• SQL文の前後に処理の追加が可能 例)不具合回避のためのALTER SESSION SET EVENT

–プロシージャの内容を差し替えることで、アプリケーションの開発生産性が向上• テーブルを用意せずとも意図するデータを返却するプロシージャを作成して、先行してアプリケーションを作成

– SQL文の記述を、SQLが得意な技術者に振り分けやすくなる

• ?/rdbms/admin/utldtree.sqlを使用した依存性分析が可能–特定のオブジェクトを使用しているプロシージャの調査が可能

21

SQL文をストアドプロシージャ化するメリット

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

DBMS_SESSION.SLEEP

• SLEEPプロシージャ:指定時間待機–例) DBMS_SESSION.SLEEP(0.5); -- 引数の待機時間は秒単位で指定

• 12cまで:DBMS_LOCKパッケージに存在

• 18c以降:DBMS_SESSIONパッケージに存在–互換性のため当面DBMS_LOCKにも存在

•変更の背景–DBMS_LOCKは強力な処理が可能なため、初期状態ではSYS以外に実行権限が付与されていない→ そんなパッケージに、汎用的に使用されるSLEEPプロシージャが格納されているのは

いい状態ではない

22

SLEEPプロシージャ格納パッケージの変更

18c~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

•略称:PTF (Polymorphic Table Function)

•基本的には従来の表関数と同様の使い方(TABLE演算子経由の呼び出し)– SELECT * FROM TABLE(関数名);

•従来の表関数との違い–テーブル名や列名を引数に取り、加工・演算した結果を出力できる

–入力・出力の列数を可変にできる

•実装に際し、ユーティリティ・パッケージDBMS_TFを使用

• パラレルパイプライン表関数として作成することが可能

23

テーブルを引数とし、入力・出力の列数を可変にできる表関数

18c~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

24

プログラム構造:PTF本体とPTF実装パッケージ

PTF本体

•SQLから呼び出される実ファンクション

•単体のファンクションとして作成。PTF実装パッケージに含めて作成することも可能

•TABLE型の仮引数を1つ、および任意の数の非TABLE型の引数が必要

•戻り値は必ずTABLE型

•1行を入力とする行セマンティックのPTFと、複数行を入力とする表セマンティックのPTFが存在

PTF実装パッケージ

• PTFの処理ロジックを実装するパッケージ

• PTF本体にて実装パッケージを指定する形式のため、必ずパッケージとして作成

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

25

サンプル:指定列以外を表示する関数(パッケージ定義部)

CREATE PACKAGE skip_col_pkg ASFUNCTION skip_col(tab TABLE,

col COLUMNS)RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;

FUNCTION describe(tab IN OUT DBMS_TF.TABLE_T, col DBMS_TF.COLUMNS_T)

RETURN DBMS_TF.DESCRIBE_T;END skip_col_pkg;

検索対象のテーブル名

除外対象の列名(複数指定可)

PTFであることの宣言と、PTF実装パッケージの指定

• PTFの実処理を担うファンクション• open→pipe_rows→closeというファンクションを定義する方式もあり

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

26

サンプル:指定列以外を表示する関数(パッケージ本体部)

CREATE PACKAGE BODY skip_col_pkg ASFUNCTION describe(tab IN OUT DBMS_TF.TABLE_T, col DBMS_TF.COLUMNS_T)

RETURN DBMS_TF.DESCRIBE_T AS new_cols DBMS_TF.COLUMNS_NEW_T;col_id PLS_INTEGER := 1;

BEGIN FOR i IN 1 .. tab.column.count() LOOP

FOR j IN 1 .. col.count() LOOPtab.column(i).PASS_THROUGH := tab.column(i).DESCRIPTION.NAME != col(j);EXIT WHEN NOT tab.column(i).PASS_THROUGH;

END LOOP;END LOOP;RETURN NULL;

END; END;

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

27

実行例(1) : SELECTリスト、WHERE句などの指定も可

SQL> select deptno, initcap(dname)2 from table(skip_col_pkg.skip_col(dept, columns(loc)))3 where deptno < 30;

DEPTNO INITCAP(DNAME)---------- ----------------------------

10 Accounting20 Research

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

多相テーブルファンクション

28

実行例(2) : WITH句の利用も可

SQL> with d as2 (select * from dept where deptno > 20)3 select * from table(skip_col_pkg.skip_col(d, columns(deptno,loc)));

DNAME----------------------------SALESOPERATIONS

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

修飾式の追加

29

より簡潔、便利な記述が可能に

DECLARETYPE t_rec IS RECORD (

col1 number,col2 number,col3 number);

v_rec t_rec;BEGIN

v_rec.col1 := 1;v_rec.col2 := 2;v_rec.col3 := 3;

END;

DECLARETYPE t_rec IS RECORD (

col1 number,col2 number,col3 number);

v_rec t_rec;BEGIN

v_rec := t_rec(1, 2, 3);END;

12c以前 18c以降

18c~

DECLARETYPE t_rec IS RECORD (

col1 number,col2 number,col3 number);

v_rec t_rec;BEGIN

v_rec := t_rec(col3 => 3,col2 => 2,col1 => 1);

END;

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

プライベート一時表

•従来のグローバル一時表に加え、プライベート一時表をサポート–グローバル一時表:定義は共有、データのみ一時的に存在

–プライベート一時表:定義もデータも一時的に存在

• テーブル名に「ORA$PTT_」で始まる接頭辞が必要–接頭辞は初期化パラメータPRIVATE_TEMP_TABLE_PREFIXで変更可能

• プライベート一時表の存在期間はトランザクション単位もしくはセッション単位

• MS SQLServerのような、プロシージャ内でプライベート一時表を多用する環境からの移植性が向上

30

他のRDBMSからの移植性の向上

18c~

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

プライベート一時表

31

移行例

CREATE PROCEDURE SP_myStoreProc@customer int, @calleid int,…

asbegin

CREATE table #temp (cmpid int ,branched, …SELECT c.cmpid,d.branched into #temp

from CallTrack d cross join cmpsetup c…

CREATE OR REPLACE PROCEDURE SP_myStoreProc(customer NUMBER, calleid NUMBER,…)

ISBEGIN

EXECUTE IMMEDIATE 'CREATE PRIVATE

TEMPORARY TABLE ora$ptt_temp

(cmpid number,….) ON COMMIT DROP DEFINITION’;EXECUTE IMMEDIATE ‘INSERT INTO ora$ptt_temp

(cmpid….) SELECT …’;

END;

SQLServer Oracle

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

アジェンダ

32

2

3

More Faster!!- パフォーマンス向上のための新機能PickUp

More Convenient!!- パフォーマンス以外のPL/SQL新機能PickUp

More Powerful!!- PL/SQLの開発生産性向上

1

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

PL/SQLの開発にメモ帳を使っていませんか。。。?

33

Oracle SQL Developerを使いましょう!!

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle SQL Developer

• 基本機能

– オブジェクトの閲覧と作成

– PL/SQLの編集とデバッグ

– SQL Worksheet (コマンドとスクリプト)

– SQL実行計画の表示

– 異種データベースからの移行(マイグレーション)

– PL/SQL Unit Test

– SQL Developer Data Modeler

• 最新バージョンは18.4

• zipファイルを解凍するのみの簡単インストール

GUIベースのOracle Database用統合開発環境(IDE)

34

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle SQL Developer as PL/SQL IDE

• スニペット

• カーソル位置の括弧に対応する括弧の強調

• 使い勝手の変更

– インデント文字(スペース/タブ)

– 文字コード、フォントの種類とサイズ

– インデント幅 等

• 外部ソース管理システムとの連携

– GitもしくはSubversion

PL/SQLの編集

35

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle SQL Developer as PL/SQL IDE

• デバッグモード

– ブレークポイントの設定

– ステップ実行

– トレース実行 等

• スマートデータ

– 変数の状態(格納値)を確認

• ユニット・テスト

– テストケースのリポジトリ管理

– テストケースの作成支援

– ユニット・テスト・スイート(ユニット・テストをまとめたもの)の作成と実行

PL/SQLのデバッグ

36

デバッグモードとスマートデータ

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle Developer Tools for Visual Studio (ODT)

• サーバー エクスプローラー

– DB内部をツリー構造で表示

– Oracle Wizards and Designers

• Oracle Data Window

• Oracle Database Project

• PL/SQLエディタ、デバッガ

• Oracle Query Window(問合せウィンドウ)

• SQL*Plus スクリプトの実行

• 自動コード生成

– WinForm 、ASP.NET

• .NETストアド・プロシージャ作成

Oracle Databaseおよび.NET開発を容易かつ迅速に

37

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle Database Extensions for .NET(ODE.NET).NETで作成したストアド・プログラムの利用

開発

配布

C++ / C# / VB.NETServer Project Oracle Database

Extensions for .NET

MicrosoftVisual Studio

Oracle Developer Tools for Visual Studio .NET

(ODT)

クライアントアプリケーション

DLLの作成(foo.dll)

ビルド

PL/SQLストアド・プログラム

DLL

• Oracle DatabaseのWindows版のみにてサポートされる機能

• ODT.NETで作成

38

Oracle Database

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

テック・ナイトアーカイブ資料と お役立ち情報

各回テック・ナイトセッション資料ダウンロードサイト

oracle technight技術コラム津島博士のパフォーマンス講座

技術コラムしばちょう先生の試して納得!DBAへの道

もしもみなみんがDBをクラウドで動かしてみたら

39

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

〜 みなさまの投稿をお待ちしております 〜

#OracleTechNight

Twitter

40

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 41

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |

Oracle Digitalは、オラクル製品の導入をご検討いただく際の総合窓口。

電話とインターネットによるダイレクトなコニュニケーションで、どんなお問い合わせにもすばやく対応します。もちろん、無償。どんなことでも、ご相談ください。

42

Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |