0

ユーザーに関する情報を格納するテーブルがあります。テーブルの構造は次のとおりです。

CREATE TABLE PERSONS 
(
  ID NUMBER(20, 0) NOT NULL,
  FIRSTNAME VARCHAR2(40), 
  LASTNAME VARCHAR2(40),
  BIRTHDAY DATE, 
  CONSTRAINT PERSONEN_PK PRIMARY KEY 
  (ID)
  ENABLE 
);

いくつかのテスト データを挿入した後:

SET DEFINE OFF;
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('1','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('2','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('3','Carl','Carlchen',to_date('01.01.12','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('4','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('5','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values ('6','Carl','Carlchen',to_date('01.01.12','DD.MM.RR'));

特定のユーザーの重複をすべて選択したい。たとえば、「Max Mustermann」を使用してみましょう。

SELECT p.id,p.firstname,p.lastname,p.birthday
  FROM persons p
  WHERE p.firstname = 'Max'
    AND p.lastname = 'Mustermann'
    AND p.birthday = to_date('31.10.1989','dd.mm.yyyy')
  ORDER BY p.firstname,p.lastname;

これにより、次のような結果が得られます。

id  first   last        birthday
=================================
1   Max     Mustermann  31.10.89
2   Max     Mustermann  31.10.89
4   Max     Mustermann  31.10.89
5   Max     Mustermann  31.10.89

大文字と小文字を区別しない比較を行いたいので、次のように Lower (および Trim) を使用してクエリを変更します。

SELECT p.id,p.firstname,p.lastname,p.birthday
  FROM persons p
  WHERE lower(trim(p.firstname)) = lower(trim('mAx '))
    AND lower(trim(p.lastname)) = lower(trim('  musteRmann  '))
    AND p.birthday = to_date('31.10.1989','dd.mm.yyyy')
  ORDER BY p.lastname,p.firstname;

順番が変わってびっくり!

id  first   last        birthday
=================================
1   Max     Mustermann  31.10.89
5   Max     Mustermann  31.10.89
4   Max     Mustermann  31.10.89
2   Max     Mustermann  31.10.89

lower() を使用するだけで順序が変わるのはなぜですか(trim() なしで使用しても同じ結果になります)!? ORDER BY に id 列を追加することで、安定した順序を取得できます。しかし、lower() は順序付けに影響を与えるべきではありませんか?

ORDER BY に id 列も使用することによる回避策:

SELECT p.id,p.firstname,p.lastname,p.birthday
  FROM persons p
  WHERE p.firstname = 'Max'
    AND p.lastname = 'Mustermann'
    AND p.birthday = to_date('31.10.1989','dd.mm.yyyy')
  ORDER BY p.firstname,p.lastname,p.id;

SELECT p.id,p.firstname,p.lastname,p.birthday
  FROM persons p
  WHERE lower(trim(p.firstname)) = lower(trim('mAx '))
    AND lower(trim(p.lastname)) = lower(trim('  musteRmann  '))
    AND p.birthday = to_date('31.10.1989','dd.mm.yyyy')
  ORDER BY p.lastname,p.firstname,p.id;
4

2 に答える 2

1

なしでは注文できませんorder by clause。(古いリリースで多くの人をだまされた) ように見えることもありますがgroup by、それは単なる偶然であり、信頼してはなりません。あなたの場合、いくつかの列で並べ替えていますが、その並べ替え内の重複がさらに暗黙的に順序付けされますが、これは発生しません-または少なくとも信頼できません。

この場合、Oracle は、ブロックからデータを読み取る方法の副作用として、挿入した順序で最初のクエリの行を取得する可能性があり、order by実際に変更せずにそのセット内で行を並べ替えます (または非常に可能性が高い) 。それorder byが無意味であることに気付いた場合、内部的にステップをスキップしています; 説明計画はそれを教えてくれます)。

レコードが作成される順序を変更すると、次のようになります。

...
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values
('5','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
Insert into PERSONS (ID,FIRSTNAME,LASTNAME,BIRTHDAY) values
('4','Max','Mustermann',to_date('31.10.89','DD.MM.RR'));
...

結果の「順序」も変更されます。

SELECT p.id,p.firstname,p.lastname,p.birthday
  FROM persons p
  WHERE p.firstname = 'Max'
    AND p.lastname = 'Mustermann'
    AND p.birthday = to_date('31.10.1989','dd.mm.yyyy')
  ORDER BY p.firstname,p.lastname;

        ID FIRSTNAME            LASTNAME             BIRTHDAY
---------- -------------------- -------------------- ---------
         1 Max                  Mustermann           31-OCT-89
         2 Max                  Mustermann           31-OCT-89
         5 Max                  Mustermann           31-OCT-89
         4 Max                  Mustermann           31-OCT-89

関数を取得すると、たとえレコードがid順番に挿入されたとしても (内部的には DB とは関係ありません)、その幸せな事故がウィンドウの外に出るのに十分なほど変化します。lower()順序を変更しているわけではありません。もう運が悪いだけです。

句で完全に指定しない限り、注文を期待したり、頼ったりすることはできません。order by

于 2013-04-24T07:55:44.110 に答える