oracle utl_lms 带变量的整数替换

Posted

技术标签:

【中文标题】oracle utl_lms 带变量的整数替换【英文标题】:oracle utl_lms integer substitution with variables 【发布时间】:2016-05-15 18:42:41 【问题描述】:

我在使用 oracle 的 UTL_LMS.MESSAGE_FORMAT 时遇到了一个奇怪的问题。当以变量替换为目标 %d 替换时,UTL_LMS 悄悄地未能替换并中断我的调用堆栈中的异常消息传递。

UTL_LMS.FORMAT_MESSAGE 调用 VARCHAR 参数,但 doc(11gR2) 示例中的类型转换似乎与整数变量兼容。但是,我的 %d 永远不会被替换。

我希望得到一些想法/建议。下面是一个失败的例子。

运行以下:

DECLARE
  C_INTRANSITIVE_VERB CONSTANT VARCHAR2(50) := 'breakdance';
  C_SUBJECT_NOUN CONSTANT VARCHAR2(50) := 'hobbit';
  C_PREPOSITION_OBJECT CONSTANT VARCHAR2(50) := 'wookie';
  C_MULTIPLIER CONSTANT INTEGER := 19;
  C_TEMPLATE CONSTANT VARCHAR2(400) := 'The %s likes to %s with the %s %d times a day.';
BEGIN
  DBMS_OUTPUT.PUT_LINE('My integer is: '|| C_MULTIPLIER);
  DBMS_OUTPUT.PUT_LINE(
      UTL_LMS.FORMAT_MESSAGE(C_TEMPLATE,C_SUBJECT_NOUN,C_INTRANSITIVE_VERB,C_PREPOSITION_OBJECT,C_MULTIPLIER)
  );
END;
/

产量:

我的整数是:19

霍比特人喜欢每天与伍基人一起跳霹雳舞。

但是,以下将原始 int 转换为精细:

DECLARE
  C_INTRANSITIVE_VERB CONSTANT VARCHAR2(50) := 'breakdance';
  C_SUBJECT_NOUN CONSTANT VARCHAR2(50) := 'hobbit';
  C_PREPOSITION_OBJECT CONSTANT VARCHAR2(50) := 'wookie';
  C_MULTIPLIER CONSTANT INTEGER := 19;
  C_TEMPLATE CONSTANT VARCHAR2(400) := 'The %s likes to %s with the %s %d times a day.';
BEGIN
  DBMS_OUTPUT.PUT_LINE('My integer is: '|| C_MULTIPLIER);
  DBMS_OUTPUT.PUT_LINE(
      UTL_LMS.FORMAT_MESSAGE(C_TEMPLATE,C_SUBJECT_NOUN,C_INTRANSITIVE_VERB,C_PREPOSITION_OBJECT,19)
  );
END;
/

我的整数是:19

霍比特人喜欢与伍基人每天跳霹雳舞 19 次。

以下解决方法是不可取的。

DECLARE
  C_INTRANSITIVE_VERB CONSTANT VARCHAR2(50) := 'breakdance';
  C_SUBJECT_NOUN CONSTANT VARCHAR2(50) := 'hobbit';
  C_PREPOSITION_OBJECT CONSTANT VARCHAR2(50) := 'wookie';
  C_MULTIPLIER CONSTANT INTEGER := 19;
  C_TEMPLATE CONSTANT VARCHAR2(400) := 'The %s likes to %s with the %s %d times a day.';
BEGIN
  DBMS_OUTPUT.PUT_LINE('My integer is: '|| C_MULTIPLIER);
  DBMS_OUTPUT.PUT_LINE(
      UTL_LMS.FORMAT_MESSAGE(C_TEMPLATE,C_SUBJECT_NOUN,C_INTRANSITIVE_VERB,C_PREPOSITION_OBJECT,TO_CHAR(C_MULTIPLIER))
  );
END;
/

我的整数是:19

霍比特人喜欢与伍基人每天跳霹雳舞 19 次。

    为什么 FORMAT_MESSAGE 接受原始整数,但在 INTEGER 类型(或一般 NUMBER 类型)变量上失败? 是否有更好的预打包 (11g) dbms 消息格式化程序可用? 关于在 oracle 11g 中进行干净的消息格式设置的任何其他建议?我会考虑包装 java 的 MessageFormat/String#format(),或者制作一个处理 char 类型转换的 FORMAT_MESSAGE 委托,但是对于所有需要它的数据库,我宁愿避免这种情况,而且我不太热衷于“只需记住“to_char() 无处不在,因为失败是相当安静的。

谢谢!

【问题讨论】:

【参考方案1】:

查看文档

https://docs.oracle.com/database/121/ARPLS/u_lms.htm#ARPLS71196

该示例指定 PLS_INTEGER 而不是整数或数字。我已经对此进行了测试,并且使用 PLS_INTEGER 可以在 Integer 无法使用的情况下使用。

我知道这不是一个理想的解决方案,我不确定将您的变量定义为 pls_integer 是否适合您。但可能会有所帮助。

DECLARE
  C_INTRANSITIVE_VERB CONSTANT VARCHAR2(50) := 'breakdance';
  C_SUBJECT_NOUN CONSTANT VARCHAR2(50) := 'hobbit';
  C_PREPOSITION_OBJECT CONSTANT VARCHAR2(50) := 'wookie';
  C_MULTIPLIER CONSTANT PLS_INTEGER := 19;
  C_TEMPLATE CONSTANT VARCHAR2(400) := 'The %s likes to %s with the %s %d times a day.';
BEGIN
  DBMS_OUTPUT.PUT_LINE('My integer is: '|| C_MULTIPLIER);
  DBMS_OUTPUT.PUT_LINE(
      UTL_LMS.FORMAT_MESSAGE(C_TEMPLATE,C_SUBJECT_NOUN,C_INTRANSITIVE_VERB,C_PREPOSITION_OBJECT,C_MULTIPLIER)
  );
END;

给出输出

My integer is: 19
The hobbit likes to breakdance with the wookie 19 times a day.

【讨论】:

感谢 Shaun 深入了解打开这么长时间的帖子。如果函数只处理数字类型之间的类型转换当然会更好,虽然二进制整数并不总是有效,但这符合观察到的模式并为行为提供一些有用的上下文。它还提供了更多研究。我可以接受。谢谢

以上是关于oracle utl_lms 带变量的整数替换的主要内容,如果未能解决你的问题,请参考以下文章

CS50:LIKE 运算符,带 % 扩展的变量替换

如何避免 Oracle SQL Developer 中的变量替换

使用 Oracle 替换变量进行查询

如何在 Oracle APEX 中使用替换变量

Oracle的SQL语句中的变量替换

Oracle PLSQL:如何根据每个值使用替换变量?