在 PL/SQL 函数的 EXECUTE IMMEDIATE 中使用 UDT 变量

2023-12-14

我正在使用 Oracle 11g 在 PL/SQL 上构建一个函数。

我试图在 EXECUTE IMMEDIATE 语句中使用表变量,但它不起作用,如您所见:

ERROR at line 1:
ORA-00904: "CENTER_OBJECTS": invalid identifier
ORA-06512: at "HIGIIA.KNN_JOIN", line 18

我正在使用的代码是...

一、类型定义

CREATE TYPE join_t IS OBJECT (
   inn                          char(40),
   out                        char(40)
);
/


CREATE TYPE join_jt IS TABLE OF join_t;
/

CREATE TYPE blob_t IS OBJECT (
   id           CHAR(40),
   fv           BLOB
);
/

CREATE TYPE blob_tt IS TABLE OF blob_t;
/

其功能是:

create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2, blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER ) RETURN join_jt
IS
var_fv BLOB;
var_id CHAR(40);
center_objects blob_tt := blob_tt();
retval join_jt := join_jt ();
join_table join_jt := join_jt();
sql_stmt1 varchar2(400);
sql_stmt2 varchar2(400);
BEGIN
    sql_stmt1 := 'SELECT blob_t(ROWIDTOCHAR(rowid),' || blob_col1 || ') FROM ' || tab_out;
    sql_stmt2 := 'SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) FROM ' || tab_inn || ' r  WHERE ' || dist_alg || '_knn(r.' || blob_col2 || ',  center_objects(idx).' ||   blob_col1 || ')<=' || kv;
    dbms_output.put_line(sql_stmt2);    
    EXECUTE IMMEDIATE sql_stmt1 BULK COLLECT INTO center_objects;
    for idx in center_objects.first()..center_objects.last()
                loop
                --SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) BULK COLLECT INTO join_table FROM londonfv r WHERE manhattan_knn(r.fv, center_objects(idx).fv) <=5;
                EXECUTE IMMEDIATE sql_stmt2 BULK COLLECT INTO join_table;   
            for idx2 in join_table.first()..join_table.last()
                   loop
                            retval.extend();
                        retval(retval.count()) := join_table(idx2);
                       end loop;
            end loop;
RETURN retval;
END;
/

运行该函数:

select * from TABLE(knn_join('london','cophirfv','fv','fv','manhattan',5)); 

我正在尝试使用运行语句 'SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) BULK COLLECT INTO join_table FROM london r WHERE manhattan_knn(r.fv, center_objects(idx).fv)

有人可以帮我吗?

提前致谢!


您无法在动态 SQL 语句中引用本地 PL/SQL 变量,因为它超出了动态调用所使用的 SQL 上下文的范围。您可以替换您的第一个电话:

SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) FROM ' ...

使用绑定变量:

SELECT join_t(ROWIDTOCHAR(r.rowid), :id FROM ' ...
EXECUTE IMMEDIATE ... USING center_objects(idx).id ...

但是当对象属性也可变时你不能做什么:

... ',  center_objects(idx).' ||   blob_col1 || ')<='...

虽然 - 至少在您展示的示例中 - 唯一可用的对象属性名称是fv,无论传递给函数的表列名称如何 - 以便可以进行硬编码;因此可以使用绑定变量:

... ',  :fv)<='...
EXECUTE IMMEDIATE ... USING center_objects(idx).id, center_objects(idx).fv ...

and the kvvalue 也应该是一个绑定变量,所以你最终会得到:

create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2,
  blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER )
RETURN join_jt
IS
  center_objects blob_tt := blob_tt();
  retval join_jt := join_jt ();
  join_table join_jt := join_jt();
  sql_stmt1 varchar2(400);
  sql_stmt2 varchar2(400);
BEGIN
  sql_stmt1 := 'SELECT blob_t(ROWIDTOCHAR(rowid),' || blob_col1 || ') FROM ' || tab_out;
  sql_stmt2 := 'SELECT join_t(ROWIDTOCHAR(r.rowid), :id) FROM ' || tab_inn || ' r  WHERE '
    || dist_alg || '_knn(r.' || blob_col2 || ',  :fv)<= :kv';
  dbms_output.put_line(sql_stmt1);    
  dbms_output.put_line(sql_stmt2);    
  EXECUTE IMMEDIATE sql_stmt1 BULK COLLECT INTO center_objects;
  for idx in center_objects.first()..center_objects.last()
  loop
    EXECUTE IMMEDIATE sql_stmt2 BULK COLLECT INTO join_table
    USING center_objects(idx).id, center_objects(idx).fv, kv;   
    for idx2 in join_table.first()..join_table.last()
    loop
      retval.extend();
      retval(retval.count()) := join_table(idx2);
    end loop;
  end loop;
  RETURN retval;
END;
/

据我所知,您仍然可以在动态 SQL 语句中进行连接,并消除循环和中间的需要center_objects and join_table收藏:

create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2,
  blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER )
RETURN join_jt
IS
  retval join_jt;
  sql_stmt varchar2(400);
BEGIN
  sql_stmt := 'SELECT join_t(ROWIDTOCHAR(tinn.rowid), ROWIDTOCHAR(tout.rowid))'
    || ' FROM ' || tab_inn || ' tinn JOIN ' || tab_out || ' tout'
    || ' ON ' || dist_alg || '_knn(tinn.fv, tout.fv) <= :kv';

  dbms_output.put_line(sql_stmt);
  EXECUTE IMMEDIATE sql_stmt BULK COLLECT INTO retval USING kv;
  RETURN retval;
END;
/

当您按照所示方式调用它时:

select * from TABLE(knn_join('london','cophirfv','fv','fv','manhattan',5)); 

这相当于硬编码:

SELECT join_t(ROWIDTOCHAR(tinn.rowid), ROWIDTOCHAR(tout.rowid))
FROM london tinn
JOIN cophirfv tout
ON manhattan_knn(tinn.fv, tout.fv) <= 5

...所以我想您可以首先验证该硬编码版本是否为您提供了您期望的结果。 (当然,向问题添加样本数据和预期结果会有所帮助)。

该连接条件可能会很昂贵,具体取决于函数正在执行的操作、每个表中的行数(因为每个表中的每一行都必须与另一个表中的每一行进行比较)、是否实际上有其他过滤器等。但循环版本会更糟。如果没有更多信息,无论如何,我们对此无能为力。

顺便说一句,使用varchar2代替char对于对象属性来说会比较正常;这也是返回的数据类型the rowidtochar()功能.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 PL/SQL 函数的 EXECUTE IMMEDIATE 中使用 UDT 变量 的相关文章

  • 获取查询的行号

    我有一个查询将返回一行 当表排序时 有什么方法可以找到我正在查询的行的行索引吗 我试过了rowid但当我期待第 7 行时却得到了 582 Eg CategoryID Name I9GDS720K4 CatA LPQTOR25XR CatB
  • 如何检测 Postgres 中持有锁的查询?

    我想不断跟踪 postgres 中的互锁 我碰到锁具监控 https wiki postgresql org wiki Lock Monitoring文章并尝试运行以下查询 SELECT bl pid AS blocked pid a us
  • SQL 大表中的随机行(使用 where 子句)

    我有一个网站 人们可以在其中对汽车进行投票 向用户展示 4 辆汽车 他 她可以投票选出他们最喜欢的汽车 桌子cars有重要的列 car id int 10 not auto increment so has gaps views int 7
  • 如何在 Oracle 中列出活动/打开的连接?

    是否有任何隐藏表 系统变量或其他东西可以显示给定时刻的活动连接 Use the V SESSION http docs oracle com cd B19306 01 server 102 b14237 dynviews 2088 htm
  • 使用MySQL计算单个表中借方和贷方的余额

    下面的 MySQL 表包含带有关联金额的借方或贷方 操作 如何选择具有非零 余额 的所有 CLIENT ID 我尝试将表连接到自身以计算所有借方和贷方总额 但有些东西无法正常工作 CLIENT ID ACTION TYPE ACTION A
  • 是否允许在流水线 PL/SQL 表函数中使用 SELECT?

    管道函数的文档指出 在 SQL 语句 通常是SELECT 并且在大多数示例中 管道函数用于数据生成或转换 接受客户作为参数 但不发出任何 DML 语句 现在 从技术上讲 可以使用 SELECT 而不会出现 Oracle 中的任何错误 ORA
  • Postgres、更新和锁定顺序

    我正在研究 Postgres 9 2 有 2 个更新 每个更新都有自己的事务 一个看起来像 UPDATE foo SET a 1 WHERE b IN 1 2 3 4 另一个也类似 UPDATE foo SET a 2 WHERE b IN
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 如何通过循环变量在 dbt 中多次运行 SQL 模型?

    我有一个 dbt 模型 测试模型 接受地理变量 zip state region 在配置中 我想通过循环变量来运行模型三次 每次使用不同的变量运行它 问题是 我有一个如下所示的宏 它将变量附加到输出表名称的末尾 即运行测试模型 with z
  • Yii 查询时对相关模型的限制

    我遇到了极限问题 我正在使用的代码如下 model PostCategory model record model gt with array posts gt array order gt posts createTime DESC li
  • 外键引用多个表

    我有4张桌子 A ida name B ida B specific stuff C ida C specific stuff D ida D specific stuff 我希望另一个表 E 可以仅引用 B 或 C 而不是 D 我可以在其
  • 通过将行旋转为动态数量的列来在 MySQL 中创建摘要视图

    我在 MySQL 中有一个表 其中包含以下字段 id company name year state 同一客户和年份有多行 以下是数据示例 id company name year state 1 companyA 2008 1 2 com
  • SQL Server 中的派生表

    我有这两个疑问 我不知道如何将它们组合在一起来制作派生表 我假设使用第二个查询作为主查询 并在主查询的 FROM 子句中使用第一个查询 SELECT EmailAddress Orders OrderID SUM ItemPrice Qua
  • 更新每组单行

    的背景 我有一个临时表 其中包含唯一的 rowID OrderNumber 和 guestCount 等信息 RowID 和 OrderNumber 已存在于该表中 并且我正在运行一个新查询来填充每个 orderNumber 缺少的 gue
  • 使用 Powershell SQL 将数据提取到 Excel

    我想使用 powershell 将数据从 SQL Server 提取到新的 excel 文件 对于小型数据集 我的代码可以工作 但某些表的行数超过 100 000 行 这将需要很长时间 我不在 SQl 服务器中使用该实用程序的原因是因为我想
  • 当我输入 dateadd 或 datediff 代码时,我总是收到此错误“ORA-00904“DATEADD”无效标识符。”

    我有一个大学项目 并且有一个包含入院和出院日期属性的患者表 我需要删除超过 7 年的记录 我使用了以下代码 delete from patient where dis date gt datedadd yy 7 getdate 我收到错误
  • 在 Doctrine DQL 中选择 count() ,并使用左连接多对多单向关系,其中用户没有关系特定组

    情况 我尝试在 DQL 中为不属于特定组的用户选择 count 标准ManyToMany之间的单向关系User and Group实体来自FOSUserBundle and SonataUserBundle 系统 Symfony 2 5 D
  • 部署 dacpac 所需的权限

    我正在尝试使用 sqlpackage exe 在租户上部署 dacpac 目前 我正在向将部署此功能的帐户授予 SysAdmin 或 db owner 权限 并且它工作正常 但在生产中 如果目标租户数据库属于其他应用程序 我可能无法获得这些
  • 如何在SqlAlchemy中执行“左外连接”

    我需要执行这个查询 select field11 field12 from Table 1 t1 left outer join Table 2 t2 ON t2 tbl1 id t1 tbl1 id where t2 tbl2 id is
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐