Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Oracle Select * trả về các hàng nhưng Select count (1) trả về 0

Kết quả sai có thể do hỏng, lỗi và các tính năng âm thầm thay đổi câu lệnh SQL.

  1. Chỉ mục tham nhũng. Rất hiếm khi một chỉ mục bị hỏng và dữ liệu từ một chỉ mục không khớp với dữ liệu từ một bảng. Điều này gây ra kết quả không mong muốn khi kế hoạch truy vấn thay đổi và một chỉ mục được sử dụng, nhưng mọi thứ trông bình thường đối với các truy vấn khác nhau sử dụng quyền truy cập bảng. Đôi khi chỉ cần xây dựng lại các đối tượng có thể khắc phục điều này. Nếu không, bạn sẽ cần tạo một trường hợp thử nghiệm có thể tái tạo hoàn toàn (bao gồm cả dữ liệu); hoặc đăng nó ở đây hoặc gửi nó đến Bộ phận hỗ trợ của Oracle. Có thể mất nhiều giờ để tìm ra điều này.
  2. Lỗi. Rất hiếm khi lỗi có thể khiến các truy vấn bị lỗi khi trả về hoặc thay đổi dữ liệu. Một lần nữa, cần phải có một trường hợp thử nghiệm có thể tái tạo hoàn toàn để chẩn đoán điều này và có thể mất một lúc.
  3. Tính năng chuyển đổi SQL Có một số cách để thay đổi các câu lệnh SQL một cách minh bạch. Xem xét Cơ sở dữ liệu riêng ảo (VPD), DBMS_ADVANCED_REWRITE và Khung dịch SQL.

Để loại trừ số 3, đoạn mã dưới đây chỉ cho bạn một trong những cách xấu để thực hiện việc này và cách phát hiện nó. Đầu tiên, tạo lược đồ và một số dữ liệu:

CREATE TABLE TRACKING (
  A_ID NUMBER,
  D_CODE NUMBER,
  HOD NUMBER,
  ADR_CNT NUMBER,
  TTL_CNT NUMBER,
  CREATED DATE,
  MODIFIED DATE
);
CREATE INDEX HOD_D_CODE_IDX ON TRACKING (HOD, D_CODE);
CREATE UNIQUE INDEX TRACKING_PK ON TRACKING (A_ID, D_CODE, HOD);
CREATE INDEX MOD_DATE_IDX ON TRACKING (MODIFIED);
ALTER TABLE TRACKING ADD CONSTRAINT TRACKING_PK PRIMARY KEY (A_ID, D_CODE, HOD);

insert into tracking values (1,2,3,4,5,sysdate,sysdate);
commit;

Lúc đầu, mọi thứ hoạt động như mong đợi:

SQL> SELECT * FROM TRACKING;

      A_ID     D_CODE        HOD    ADR_CNT    TTL_CNT CREATED   MODIFIED
---------- ---------- ---------- ---------- ---------- --------- ---------
         1          2          3          4          5 17-JUN-16 17-JUN-16

SQL> SELECT COUNT(1) FROM TRACKING;

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

Sau đó, ai đó làm điều này:

begin
  sys.dbms_advanced_rewrite.declare_rewrite_equivalence(
    'april_fools',
    'SELECT COUNT(1) FROM TRACKING',
    'SELECT 0 FROM TRACKING WHERE ROWNUM = 1',
    false);
end;
/

Bây giờ kết quả là "sai":

SQL> ALTER SESSION SET query_rewrite_integrity = trusted;

Session altered.

SQL> SELECT COUNT(1) FROM TRACKING;

  COUNT(1)
----------
         0

Điều này có thể được phát hiện bằng cách xem kế hoạch giải thích. Trong ví dụ bên dưới, Predicate 2 - filter(ROWNUM=1) là một manh mối cho thấy có điều gì đó không ổn, vì vị từ đó không có trong truy vấn ban đầu. Đôi khi phần "Ghi chú" của kế hoạch giải thích sẽ cho bạn biết chính xác lý do tại sao nó được biến đổi, nhưng đôi khi nó chỉ cung cấp manh mối.

SQL> explain plan for SELECT COUNT(1) FROM TRACKING;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
Plan hash value: 1761840423

------------------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                |     1 |     2 |     1   (0)| 00:00:01 |
|   1 |  VIEW             |                |     1 |     2 |     1   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY   |                |       |       |            |          |
|   3 |    INDEX FULL SCAN| HOD_D_CODE_IDX |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM=1)

15 rows selected.

(Trên một ghi chú không liên quan - luôn sử dụng COUNT(*) thay vì COUNT(1) . COUNT(1) là một huyền thoại cũ có vẻ giống như một chương trình sùng bái hàng hóa.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle xóa các hàng khỏi nhiều bảng

  2. Oracle DB Server + APEX + ORDS + JasperReports từ đầu (Phần 4)

  3. Lỗi khi thực thi thủ tục được lưu trữ Oracle trong SSRS:PLS-00306:sai số hoặc loại đối số trong lệnh gọi tới

  4. Hiển thị tên bộ phận bằng cách sử dụng con trỏ Tạo một khối PL / SQL để hiển thị tất cả tên bộ phận từ bảng Bộ phận bằng cách sử dụng con trỏ

  5. Biểu thức chính quy Oracle. Phạm vi nguy hiểm