【问题标题】:Checking if the value inserted is a Varchar or an Integer检查插入的值是 Varchar 还是 Integer
【发布时间】:2013-11-16 16:09:58
【问题描述】:

我正在使用 SQL Developer/Oracle,如果插入特定字段的值是整数或只是“字符串”,我需要检查触发器。

我试过isnumeric(),但是这个函数在Oracle中不存在。因为我在任何地方都找不到,所以在 Oracle 中的等价物是什么?

【问题讨论】:

  • 您是在问如何判断列是数字还是 varchar 数据类型,或者 varchar 列的内容是否可以转换为数字?
  • 我正在使用 if。这意味着如果插入的值是 varhchar,我将引发应用程序错误,否则我什么也不做。

标签: sql oracle integer


【解决方案1】:

从您的上一条评论到@Ben's answer

'1234' 应该被认为是一个字符串并且失败

您似乎想在插入时对文字进行数据类型检查,并允许仅插入数字数据类型的文字。 Oracle 在有意义时会进行隐式数据类型转换。例如,您的表中有一个数字数据类型的列。当您尝试将字符文字 '123' 插入该列时,尽管该文字属于字符数据类型(char,简单字符文字属于 CHAR 数据类型而不是 varchar2,但操作仍将成功默认),因为 Oracle 查看列的数据类型,然后查看字符文字的数据类型和元素并决定“是的,将字符文字转换为数字是有意义的。 '并做到了。正如@Ben 所说,让您的应用程序检查您尝试插入表中的值是数字还是字符数据类型可能会更好。

话虽如此,进行数据类型检查并只允许插入数字数据类型的文字或变量的最简单方法可能是创建一个具有一个重载函数的包,例如isnumber()。该函数的第一个版本具有varchar2 数据类型的形参,其重载版本具有number 数据类型的形参。 Oracle会根据实际参数的数据类型选择合适的函数版本:

SQL> create or replace package Util1 as
  2    function isnumber(p_val in varchar2)
  3      return varchar2;
  4    function isnumber(p_val in number)
  5      return number;
  6  end;
  7  /
Package created

SQL> create or replace package body Util1 as
  2    function isnumber(p_val in varchar2)
  3      return varchar2 is
  4    begin
  5      raise_application_error(-20000, 'Not a numeric data type');
  6    end;
  7  
  8    function isnumber(p_val in number)
  9       return number is
 10    begin
 11      return p_val;
 12    end;
 13  end;
 14  /
Package body created

当您使用数字数据类型的实参调用util1.isnumber() 函数时,它只会将其返回,而当使用字符数据类型的实参调用该函数时,将引发异常。

SQL> create table t1(col number);
Table created

SQL> insert into t1(col) values(util1.isnumber(123));
1 row inserted

SQL> commit;
Commit complete

SQL> insert into t1(col) values(util1.isnumber('123'));

ORA-20000: Not a numeric data type
ORA-06512: at "HR.UTIL1", line 5

SQL> insert into t1(col) values(util1.isnumber('12345f'));

ORA-20000: Not a numeric data type
ORA-06512: at "HR.UTIL1", line 5

注意由于隐式数据类型转换,这种方法在触发器中不起作用。在触发器中,您必须执行以下操作:

 :new.col_name := util1.isnumber(:new.col_name)

由于col_namenumber 数据类型,Oracle 将始终调用带有数字数据类型形式参数的isnumber() 函数版本,即使插入的实际值是(比如)'123',插入也会成功。

【讨论】:

  • 这是一个相当聪明的方法;我喜欢!
【解决方案2】:

我正在使用如果。这意味着如果插入的值是 varhchar,我将引发应用程序错误,否则我什么也不做。

当您将字符插入数字字段时,您会收到“无效数字”异常 (ORA-01722)。这使您的选择更容易; 不要测试你插入的字符串是否是一个字符。当用户将字符插入数字字段并作为应用程序错误重新引发时捕获引发的异常(如果您真的觉得必须这样做)。

那么根本不需要测试。

例如:

create table test ( a number );

begin
   insert into test values ('a');
exception when INVALID_NUMBER then
   raise_application_error(-20000, 'The number wasn''t a number');
end;
/

值得注意的是,您还可以测试应用程序代码中是否有数字(如果它是应用程序)。这样您就不必往返于数据库了。

【讨论】:

  • 我真的需要 re_raise,因为这是一个大学项目,我的老师会尽其所能来破坏我的代码。因此,如果我有自定义例外,我可以向他展示我考虑了所有可能性,你明白吗?
  • 这是一个“商业决策”@André;我个人通常不赞成掩盖数据库中的错误。如果应用程序捕获异常并决定如何处理它会更好,因为去除了一层混淆。
  • 这里有个小问题——隐式数据类型转换。 OP 需要定义整数和字符串。是的,如果一列是(比如说)数字数据类型并且您要插入一个非数字字符,那么是的,将引发错误 ORA-01722。但是,当列是数字数据类型并且您尝试插入 '1233'(仍然是字符文字,而不是数字)时,将发生隐式数据类型转换。
  • 是否存在 Oracle 不会 隐式转换 @Nicholas 的情况?如果它是一个有效的数字,那么据我所知,it always will
  • 对。但我说的是 OP 如何定义整数和字符串。 '123' 是字符串还是数字(它现在不是纯数字,但它会在隐式转换后),insert 在这种情况下应该成功还是失败?是的,'a' 不是数值,插入应该会失败。 123 显然是一个数字,insert 应该成功。现在,OP将如何定义'1234'?应该将其视为数字并成功还是应将其视为字符串并失败?
猜你喜欢
  • 2012-05-16
  • 2018-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
  • 1970-01-01
  • 2012-05-17
相关资源
最近更新 更多