count(*)产生正常select语句和触发器的不同结果

时间:2017-04-21 05:55:41

标签: oracle select plsql triggers count

我在SQLDeveloper中遇到了一个奇怪的问题。

我有一个正常的select语句,如:SELECT COUNT(*) FROM demo WHERE NAME='ABC'; 上面的查询给出了结果1。 运行与SELECT COUNT(*) FROM demo WHERE NAME='ABC ';中相同的选择查询也会得到结果1。请注意,第二个查询中的额外附加空格不会更改计数值。

现在,在触发器中使用count(*)语句会产生不同的计数结果,并且在计算计数时会考虑空格。 为什么会发生这种情况?我使用的是SQLDeveloper版本4.1.5.21。

1 个答案:

答案 0 :(得分:1)

如果您的专栏是char而非varchar2

,则可以看到这一点
create table demo (name char(9));

insert into demo values ('ABC');

1 row inserted.

SELECT COUNT(*) FROM demo WHERE NAME='ABC';

  COUNT(*)
----------
         1

SELECT COUNT(*) FROM demo WHERE NAME='ABC      ';

  COUNT(*)
----------
         1

如果您使用相同的文本文字在触发器或任何PL / SQL块中执行完全相同的查询,则会得到相同的结果:

set serveroutput on
declare
  n number;
begin
  SELECT COUNT(*) into n FROM demo WHERE NAME='ABC'; 
  dbms_output.put_line(n);
  SELECT COUNT(*) into n FROM demo WHERE NAME='ABC      ';
  dbms_output.put_line(n);
end;
/

1
1

PL/SQL procedure successfully completed.

但是如果您使用varchar2变量来提供值而不是文本文字,则会得到不同的计数:

declare
  n number;
  v varchar2(9);
begin
  v := 'ABC';
  SELECT COUNT(*) into n FROM demo WHERE NAME=v; 
  dbms_output.put_line(n);
  v := 'ABC      ';
  SELECT COUNT(*) into n FROM demo WHERE NAME=v;
  dbms_output.put_line(n);
end;
/

0
1

PL/SQL procedure successfully completed.

使用文字文字it is treated as a char时:

  
      
  • 在表达式和条件中,Oracle将文本文字视为具有数据类型CHAR,方法是使用空白填充比较语义对它们进行比较。
  •   

然后明显的行为差异归结为blank-padded and nonpadded comparison semantics

  

使用空白填充语义,如果两个值具有不同的长度,则Oracle首先将空白添加到较短值的末尾,因此它们的长度相等。
  ...
  只要比较中的一个或两个值具有数据类型VARCHAR2或NVARCHAR2,Oracle就会使用非填充比较语义。

当您将char列与(char)文字文字进行比较时,两者都会填充到相同的长度,因此两个条件都会评估为真。使用空白填充语义,'ABC''ABC ''ABC '等等都是等效的。

当您将char列与varchar2变量进行比较时,不会发生填充,因此只有第二个条件(手动填充到与实际列值完全相同的长度)才会计算为true。填充列值'ABC '仅在变量显式设置为完全相同时才匹配变量。它不等于'ABC'或其他任何内容。

varchar2用于文本列通常要简单得多,以避免这些奇怪之处。不管怎样(根据我的经验)需要使用固定长度的字符串,如果数据的长度会有所不同,那么varchar2会更灵活,并且会占用更少的存储空间。