【问题标题】:PL/SQL UTL_HTTP.REQUEST - Curly Braces/SemicolonPL/SQL UTL_HTTP.REQUEST - 花括号/分号
【发布时间】:2021-08-13 20:12:25
【问题描述】:

我正在尝试使用 Oracle 自治数据库中的 UTL_HTTP 包调用 URL 并获得 ORA-06512:

ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "SYS.UTL_HTTP", line 1810
ORA-06512: at "SYS.UTL_HTTP", line 144
ORA-06512: at "SYS.UTL_HTTP", line 1745
ORA-06512: at line 1
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

所有网络 ACLS 等都配置正确。

有问题的 URL 需要直接在 URL 中使用 JSON,我理解这是不好的做法,但是我无法控制 API。如果我删除花括号 ( {} ) 和分号 ( : ),使用 UTL_HTTP 的请求可以工作,但输出不正确,因为 JSON 变得无效。

我尝试使用在线编码器以及 UTL_URL.ESCAPE 函数对 URL 进行编码,但出现与上述相同的错误。

来自 UTL_URL.ESCAPE 的编码是:

URL 格式的一个例子是:

https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}

我尝试使用 utl_http.request 直接选择:

SELECT UTL_HTTP.REQUEST('https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}') FROM DUAL;

并使用 PL/SQL 调用:

declare
    req UTL_HTTP.REQ;
    resp UTL_HTTP.RESP;
    val VARCHAR2(2000);
    str varchar2(1000);
begin
    req := UTL_HTTP.BEGIN_REQUEST('https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}');
    resp := UTL_HTTP.GET_RESPONSE(req);
    LOOP
        UTL_HTTP.READ_LINE(resp, val, TRUE);
        DBMS_OUTPUT.PUT_LINE(val);
    END LOOP;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
    WHEN UTL_HTTP.END_OF_BODY
THEN
    UTL_HTTP.END_RESPONSE(resp);
END;

/

如何使用 UTL_HTTP 调用此 url?

【问题讨论】:

  • 请编辑问题并显示相关的 pl/sql 代码。谢谢
  • 已编辑以显示尝试的 SQL 和 PL/SQL。
  • 您是如何尝试对 URL 进行编码的?使用utl_url.escape 或其他功能?你能显示输出吗?
  • @kfinity 我已经编辑了原始问题,并提供了有关编码的更多信息。我无法提供实际 URL 的确切输出,因为它包含数据,但示例 url 带有相同的 URL 十六进制编码。 https://example.com/rest.php?entity=contact&action=get&json=%7B%22name%22:%20%22Lorum%20Ipsum%22,%20%22end_date%22:%20%7B%22IS%20NULL%22:%201%7D,%20%22return%22:%20%22id,contact_id%22%7D 我刚刚注意到冒号没有被 UTL_URL 包编码,这可能是问题。

标签: oracle plsql


【解决方案1】:

他们在UTL_URL documentation 中谈到了这一点,但冒号是保留字符——它们在 URL 的某些部分有效,但在其他部分无效。 (根本不允许使用大括号。)been some debate 关于它们在 URL 的查询部分是否有效 - RFC 中的 ABNF 似乎说是,但是很多实现不允许它.

默认情况下,UTL_URL.ESCAPE 不会转义保留字符(因为这会搞砸https:// 部分等),但您可以通过传递 TRUE 作为第二个参数来更改它。一般来说,最佳实践似乎是转义任何可能包含它们的查询字符串中的保留字符:

req := UTL_HTTP.BEGIN_REQUEST('https://example.com/rest.php?entity=contact&action=get&json=' 
       || utl_url.escape('{"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}'
            ,TRUE));

看看有没有帮助?

【讨论】:

  • 这解决了这个问题。文档确实声明它不会转义冒号,正如您所指出的那样,这是有充分理由的。像您一样使用串联,或使用 %3A 替换冒号。您的解决方案更优雅。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-01-26
  • 2012-01-18
  • 1970-01-01
  • 2018-05-02
  • 2011-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多