11.7.2.2 pyqEvalファンクション(Autonomous Database)
ファンクションpyqEval
は、Oracle Autonomous Databaseで使用すると、ユーザー定義Python関数をコールします。ユーザーは、ユーザー定義Python関数に引数を渡すことができます。
pyqEval
は、データを自動的にロードしません。ユーザー定義のPython関数内では、透過層またはROracleデータベース接続を使用して、ユーザーがデータに明示的にアクセスまたは取得(あるいはその両方)できます。
構文
FUNCTION PYQSYS.pyqEval(
PAR_LST VARCHAR2,
OUT_FMT VARCHAR2,
SCR_NAME VARCHAR2,
SCR_OWNER VARCHAR2 DEFAULT NULL,
ENV_NAME VARCHAR2 DEFAULT NULL
)
RETURN SYS.AnyDataSet
パラメータ
パラメータ | 説明 |
---|---|
|
たとえば、入力データ型を
関連項目: 特殊な制御引数(Autonomous Database)。 |
|
ファンクションによって返される出力の形式。次のいずれかになります。
関連項目: 出力形式(Autonomous Database)。 |
|
OML4Pyスクリプト・リポジトリ内のユーザー定義Python関数の名前。 |
|
登録済Pythonスクリプトの所有者。デフォルト値は |
|
指定されたユーザー定義Python関数の実行時に使用されるconda環境の名前。 |
この例では、Python関数を定義し、OML4Pyスクリプト・リポジトリに格納します。ユーザー定義Python関数に対してpyqEval
ファンクションをコールします。
PL/SQLブロックで、pyqFun1
という名前でスクリプト・リポジトリに格納されるPython関数を作成します。
begin
sys.pyqScriptCreate('pyqFun1',
'def fun_tab():
import pandas as pd
names = ["demo_"+str(i) for i in range(10)]
ids = [x for x in range(10)]
floats = [float(x)/10 for x in range(10)]
d = {''ID'': ids, ''NAME'': names, ''FLOAT'': floats}
scores_table = pd.DataFrame(d)
return scores_table
',FALSE,TRUE); -- V_GLOBAL, V_OVERWRITE
end;
/
次に、pyqEval
ファンクションをコールします。これにより、ユーザー定義Python関数が実行されます。
PAR_LST
引数は、特殊な制御引数oml_service_level
でLOW
サービス・レベルを使用することを指定します。
OUT_FMT
引数で、文字列'JSON'
は、返される表にJSON文字列であるCLOBが含まれることを指定します。
SCR_NAME
パラメータは、コールするPython関数としてスクリプト・リポジトリ内のpyqFun1
ファンクションを指定します。
JSON出力はCLOBです。set long [length]
をコールすると、詳細出力を取得できます。
set long 500
select *
from table(pyqEval(
par_lst => '{"oml_service_level":"LOW"}',
out_fmt => 'JSON',
scr_name => 'pyqFun1'));
出力は次のようになります。
NAME
----------------------------------------------------------------------
VALUE
----------------------------------------------------------------------
[{"FLOAT":0,"ID":0,"NAME":"demo_0"},{"FLOAT":0.1,"ID":1,"NAME":"demo_1
"},{"FLOAT":0.2,"ID":2,"NAME":"demo_2"},{"FLOAT":0.3,"ID":3,"NAME":"de
mo_3"},{"FLOAT":0.4,"ID":4,"NAME":"demo_4"},{"FLOAT":0.5,"ID":5,"NAME"
:"demo_5"},{"FLOAT":0.6,"ID":6,"NAME":"demo_6"},{"FLOAT":0.7,"ID":7,"N
AME":"demo_7"},{"FLOAT":0.8,"ID":8,"NAME":"demo_8"},{"FLOAT":0.9,"ID":
9,"NAME":"demo_9"}]
1 row selected.
同じpyqFun1
スクリプトを起動する別の問合せを発行します。OUT_FMT
引数は、構造化表の出力の列名とデータ型を含むJSON文字列を指定します。
select *
from table(pyqEval(
par_lst => '{"oml_service_level":"LOW"}',
out_fmt => '{"ID":"number", "NAME":"VARCHAR2(8)", "FLOAT":"binary_double"}',
scr_name => 'pyqFun1'));
出力は次のようになります。
ID NAME FLOAT
0 demo_0 0.0
1 demo_1 0.1
2 demo_2 0.2
3 demo_3 0.3
4 demo_4 0.4
5 demo_5 0.5
6 demo_6 0.6
7 demo_7 0.7
8 demo_8 0.8
9 demo_9 0.9
10 rows selected.
次のコードを使用して、Pythonバージョン3.10に基づいて"seaborn"環境を作成し、プラガブル・データベース(PDB)が所有するオブジェクト・ストレージに環境をアップロードします。
ノート:
Conda環境の作成と管理には管理権限が必要です。create -n seaborn python=3.10 seaborn
upload seaborn --overwrite --description 'Python package for seaborn' -t python 3.10 -t
application OML4PY
データ・ビジュアライゼーション・ライブラリの'seaborn'が環境にインストールされています。
次のコードを使用して、スクリプト'test_seaborn_noinp'を作成します。
begin
sys.pyqScriptCreate('test_seaborn_noinp',
'def fun_tab():
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = np.random.multivariate_normal([0, 0], [[5, 2], [2, 2]], size=2000)
data = pd.DataFrame(data, columns=["x", "y"])
sns.displot(data["x"])
plt.title("Dist plot")
plt.show()
return "hello world" ',FALSE,TRUE); -- V_GLOBAL, V_OVERWRITE
end;
/
この例では、指定されたPythonスクリプトを実行するpyqEval関数をコールします。
PAR_LST
引数は、特殊な制御引数oml_graphics_flagを使用してスクリプトでレンダリングされたイメージを取得することを指定します。
OUT_FMT
引数で、文字列'PNG'は、Python関数によって生成されたイメージが格納されたBLOBが含まれる表を返すことを指定します。
SCR_NAME
パラメータは、コールするPython関数としてスクリプト・リポジトリ内の'test_seaborn_noinp'スクリプトを指定します。
ENV_NAME
パラメータは、Python関数を実行するConda環境である'seaborn'を指定します。
select *
from table(pyqEval(
par_lst => '{"oml_graphics_flag":true}',
out_fmt => 'PNG',
scr_name => 'test_seaborn_noinp',
scr_owner => NULL,
env_name => 'seaborn'
));
出力は次のようになります。
NAME
--------------------------------------------------------------------------------
ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
1
"hello world"
NAME
--------------------------------------------------------------------------------
ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
Lineplot
89504E470D0A1A0A0000000D4948445200000280000001E0080600000035D1DCE400000039744558
74536F667477617265004D6174706C6F746C69622076657273696F6E332E332E332C206874747073
NAME
--------------------------------------------------------------------------------
ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
3A2F2F6D6174706C6F746C69622E6F72672FC897B79C000000097048597300000F6100000F6101A8
3FA7690000682C49444154789CEDDD797C5355FE3FFE579236E9BEB7E942DBB414286B0B2D94820A
4AC7023A82A2022E2C83B801A37674147F0A2EDFCF1415114719D119293AC280CC208EC8A050D984
NAME
--------------------------------------------------------------------------------
ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
PL/SQLブロックで、Python関数create_iris_table
を定義し、create_iris_table
という名前でスクリプト・リポジトリに格納し、同じ名前でスクリプト・リポジトリに格納されている既存のユーザー定義Python関数を上書きします。
create_iris_table
関数は、irisデータ・セットをインポートしてロードし、2つのpandas.DataFrame
オブジェクトを作成した後、これらのオブジェクトの連結を返します。
BEGIN
sys.pyqScriptCreate('create_iris_table',
'def create_iris_table():
from sklearn.datasets import load_iris
import pandas as pd
iris = load_iris()
x = pd.DataFrame(iris.data, columns = ["Sepal_Length",\
"Sepal_Width", "Petal_Length", "Petal_Width"])
y = pd.DataFrame(list(map(lambda x: {0:"setosa", 1: "versicolor",\
2: "virginica"}[x], iris.target)),\
columns = ["Species"])
return pd.concat([y, x], axis=1)',
FALSE, TRUE); -- V_GLOBAL, V_OVERWRITE
END;
/
CREATE TABLE IRIS AS
(SELECT * FROM pyqEval(
NULL,
'{"Species":"VARCHAR2(10)","Sepal_Length":"number",
"Sepal_Width":"number","Petal_Length":"number",
"Petal_Width":"number"}',
'create_iris_table'
));