在MonetDB中混合Python和SQL是将大量业务逻辑移入数据库服务器的良好开端。但是,当前的文档包含了这个游戏中新手需要采取的一些障碍。考虑以下功能:
sql>select * from getsourceattributes('tables');
+---------------+
| c |
+===============+
| id |
| name |
| schema_id |
| query |
| type |
| system |
| commit_action |
| access |
| temporary |
+---------------+
和下表收集一些统计数据:
create table dummy(tbl string, col string, stat integer);
现在知道ptbl是一个numpy数组,我尝试了以下内容:
create function gatherStatistics(ptbl string)
returns string
language python {
for p in ptbl:
attr = _conn.execute("select * from getSourceAttributes('"+ str(p) +"');")
for col in attr :
stat = _conn.execute("select count(*) from "+ str(p) +";")
_conn_execute("insert into dummy values('"+ str(p)+"','"+ str(col) +"',"+ str(stat)+");")
return ptbl;
};
并使用
进行调用select gatherstatistics('tables');
SELECT: no such table 't'
Python exception
3. attr = _conn.execute("select * from getSourceAttributes('"+ str(p) +"');")
4. for col in attr :
5. stat = _conn.execute("select count(*) from "+ str(p) +";")
6. _conn_execute("insert into dummy values('"+ str(p)+"','"+ str(col) +"',"+str(stat)+");")
7. return ptbl;
SQL Query Failed: ParseException:SQLparser:42S02!SELECT: no such table 't'
答案 0 :(得分:0)
您遇到的问题是您将标量字符串视为数组。您调用 SELECT gatherstatistics('tables'); 并迭代 ptbl 的值。在这种情况下,您将迭代字符串'tables'的字符,第一个字符是't'字符。
如果使用列作为输入调用函数,则Python UDF中的变量将转换为(1)NumPy数组;或者(2)标量值,如果使用标量值作为输入调用函数。
考虑以下函数,它将输入参数的类型作为字符串返回:
CREATE FUNCTION get_type(s STRING)
RETURNS STRING
LANGUAGE PYTHON
{
return str(type(s))
};
现在,如果我们使用标量值查询它,我们得到以下输出:
SELECT get_type('hello');
+------------------+
| L2 |
+==================+
| <type 'unicode'> |
+------------------+
但是如果我们用列查询它,我们得到以下输出:
SELECT get_type(name) FROM tables;
+------------------------+
| L40 |
+========================+
| <type 'numpy.ndarray'> |
+------------------------+
通常,您将创建一个只接受一个作为给定参数的有效输入的函数。例如,您可以创建一个名为 log 的函数,该函数将数值的数组作为输入,并使用对数的标量基础。
如果要创建一个对标量值和数组值都进行操作的函数,一种简单的方法是检查输入参数的类型。如果它不是NumPy数组,我们将其转换为一个。
例如,考虑以下函数来反转字符串并对数组和标量值进行操作:
CREATE OR REPLACE FUNCTION reverse_string(s STRING)
RETURNS STRING
LANGUAGE PYTHON
{
if not isinstance(s, numpy.ndarray):
s = numpy.array([s])
return [x[::-1] for x in s]
};
SELECT reverse_string('hello');
+-------+
| L2 |
+=======+
| olleh |
+-------+
SELECT reverse_string(name) FROM tables LIMIT 3;
+-----------+
| L40 |
+===========+
| samehcs |
| sepyt |
| snoitcnuf |
+-----------+