Làm thế nào để lấy giá trị hiện tại của một chuỗi orory mà không tăng nó?


156

Có một lệnh SQL để lấy giá trị của một chuỗi không tăng nó.

Cảm ơn.

CHỈNH SỬA VÀ KẾT LUẬN

Như Justin Cave đã tuyên bố Thật không hữu ích khi cố gắng "lưu" số thứ tự như vậy

select a_seq.nextval from dual;

là đủ tốt để kiểm tra một giá trị trình tự.

Tôi vẫn giữ câu trả lời của Ollie là câu trả lời hay vì nó đã trả lời câu hỏi ban đầu. nhưng hãy tự hỏi về sự cần thiết của việc không sửa đổi trình tự nếu bạn muốn làm điều đó.


5
Tại sao? Vấn đề bạn đang cố gắng giải quyết là gì? Nếu bạn đang sử dụng trình tự một cách chính xác, bạn không bao giờ nên quan tâm giá trị trình tự nào đã được chỉ định cho các phiên khác hoặc giá trị nào có thể được chỉ định cho các phiên tiếp theo.
Hang Justin

3
Đó là kiểm tra sau khi di chuyển dữ liệu để đảm bảo chuỗi đã được cập nhật chính xác theo dữ liệu được di chuyển
frno

3
Vậy thì nhược điểm của việc đơn giản là lấy nextvalchuỗi để kiểm tra là gì? Bạn không cho rằng các chuỗi sẽ không có khoảng cách, phải không? Vì vậy, "lãng phí" một giá trị chuỗi không nên là một vấn đề.
Hang Justin

Tôi đoán bạn đã đúng, tôi không muốn thay đổi trạng thái của db cho kiểm tra đó nhưng thành thật mà nói tôi không biết tại sao. cảm ơn vì sự sáng suốt của bạn tuy nhiên tôi đã học được công cụ của bạn về trình tự, cảm ơn tất cả các bạn!
frno

Giả sử bạn có thể nhận được giá trị của một chuỗi một cách đáng tin cậy, điều tiên tri của bạn là gì mà bạn đang kiểm tra xem chuỗi đó đã được cập nhật đúng chưa?
Shannon Severance

Câu trả lời:


173
SELECT last_number
  FROM all_sequences
 WHERE sequence_owner = '<sequence owner>'
   AND sequence_name = '<sequence_name>';

Bạn có thể nhận được một loạt các siêu dữ liệu chuỗi từ user_sequences, all_sequencesdba_sequences.

Những quan điểm này hoạt động trên các phiên.

BIÊN TẬP:

Nếu chuỗi nằm trong lược đồ mặc định của bạn thì:

SELECT last_number
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Nếu bạn muốn tất cả các siêu dữ liệu thì:

SELECT *
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Hy vọng nó giúp...

EDIT2:

Một cách dài hơi để làm điều đó đáng tin cậy hơn nếu kích thước bộ đệm của bạn không phải là 1 sẽ là:

SELECT increment_by I
  FROM user_sequences
 WHERE sequence_name = 'SEQ';

      I
-------
      1

SELECT seq.nextval S
  FROM dual;

      S
-------
   1234

-- Set the sequence to decrement by 
-- the same as its original increment
ALTER SEQUENCE seq 
INCREMENT BY -1;

Sequence altered.

SELECT seq.nextval S
  FROM dual;

      S
-------
   1233

-- Reset the sequence to its original increment
ALTER SEQUENCE seq 
INCREMENT BY 1;

Sequence altered.

Chỉ cần lưu ý rằng nếu những người khác đang sử dụng trình tự trong thời gian này - họ (hoặc bạn) có thể nhận được

ORA-08004: sequence SEQ.NEXTVAL goes below the sequences MINVALUE and cannot be instantiated

Ngoài ra, bạn có thể muốn đặt bộ đệm thành NOCACHEtrước khi đặt lại và sau đó quay lại giá trị ban đầu của nó sau đó để đảm bảo rằng bạn không lưu trữ nhiều giá trị.


Chỉ cần thử nó nhưng tôi không có quyền truy cập vào bảng 'all_ resultences'. Đây có phải là một đối tượng đặc biệt mà bạn chỉ nhìn thấy với thông tin đăng nhập của quản trị viên?
frno

1
ALL_SEQUENCESlà một góc nhìn. Nếu bạn không có quyền truy cập vào nó thì hãy thử chọn USER_SEQUENCESnếu chuỗi nằm trong lược đồ mặc định của bạn. (Bạn sẽ không cần sequence_owner = '<sequence_owner>'điều khoản cho USER_SEQUENCES).
Ollie

15
Số LAST_NUMBERtrong ALL_SEQUENCESsẽ không phải là số cuối cùng mà một phiên thực sự được đưa ra và sẽ không phải là số sẽ được trả về từ một cuộc gọi đến sequence_name.nextvalnói chung. Giả sử bạn đã đặt chuỗi thành CACHEnhiều hơn 1 (mặc định là 20), LAST_NUMBERsẽ là số cuối cùng trong bộ đệm. Không có gì đảm bảo rằng con số này sẽ thực sự được trao cho bất kỳ phiên nào.
Hang Justin

2
ALTER SEQUENCE seq INCREMENT BY -1;sẽ là một vấn đề trừ khi người ta có thể đảm bảo rằng không có phiên nào khác sẽ gọi seq.nextval. Nếu không, trình tự sẽ đưa ra các giá trị trùng lặp, thường không phải là những gì người ta muốn.
Shannon Severance

1
OP đã nói "Đó là một kiểm tra sau khi di chuyển dữ liệu" vì vậy không phải là giả sử DB không được sử dụng chung nhưng nó có thể là một vấn đề nếu đây không phải là trường hợp.
Ollie

122

select MY_SEQ_NAME.currval from DUAL;

Hãy nhớ rằng nó chỉ hoạt động nếu bạn chạy select MY_SEQ_NAME.nextval from DUAL;trong các phiên hiện tại.


1
Cảm ơn một bó cho câu trả lời của bạn. Tôi phải sử dụng cái này bên trong Boomi và đang tìm kiếm một giải pháp lên xuống
học ...

0

Câu trả lời ban đầu của tôi thực tế không chính xác và tôi rất vui vì nó đã bị xóa. Mã dưới đây sẽ hoạt động theo các điều kiện sau a) bạn biết rằng không ai khác sửa đổi trình tự b) trình tự đã được sửa đổi bởi phiên của bạn. Trong trường hợp của tôi, tôi đã gặp phải một vấn đề tương tự khi tôi đang gọi một thủ tục sửa đổi một giá trị và tôi tin chắc rằng giả định này là đúng.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Đáng buồn thay, nếu bạn không sửa đổi trình tự trong phiên của mình, tôi tin rằng những người khác đã đúng khi tuyên bố rằng NEXTVAL là cách duy nhất để đi.


0

Đây không phải là một câu trả lời, thực sự và tôi đã nhập nó như một bình luận nếu câu hỏi không bị khóa. Điều này trả lời câu hỏi:

Tại sao bạn muốn nó?

Giả sử bạn có một bảng với trình tự là khóa chính và trình tự được tạo bởi trình kích hoạt chèn. Nếu bạn muốn có sẵn chuỗi cho các bản cập nhật tiếp theo cho bản ghi, bạn cần có cách để trích xuất giá trị đó.

Để đảm bảo bạn nhận được đúng, bạn có thể muốn bọc truy vấn của INSERT và RonK trong một giao dịch.

Truy vấn của RonK:

select MY_SEQ_NAME.currval from DUAL;

Trong trường hợp trên, cảnh báo của RonK không áp dụng vì việc chèn và cập nhật sẽ xảy ra trong cùng một phiên.


0

Tôi cũng đã thử sử dụng CURRVAL, trong trường hợp của tôi để tìm hiểu xem một số quy trình có chèn các hàng mới vào một số bảng với chuỗi đó là Khóa chính hay không. Giả định của tôi là CURRVAL sẽ là phương pháp nhanh nhất. Nhưng a) CurrVal không hoạt động, nó sẽ chỉ nhận được giá trị cũ vì bạn đang ở trong một phiên Oracle khác, cho đến khi bạn thực hiện NEXTVAL trong phiên của riêng bạn. Và b) a select max(PK) from TheTablecũng rất nhanh, có lẽ vì PK luôn được lập chỉ mục. Hoặc select count(*) from TheTable. Tôi vẫn đang thử nghiệm, nhưng cả hai CHỌN có vẻ nhanh.

Tôi không bận tâm đến một khoảng trống trong một chuỗi, nhưng trong trường hợp của tôi, tôi đã nghĩ đến việc bỏ phiếu rất nhiều, và tôi sẽ ghét ý tưởng về những khoảng trống rất lớn. Đặc biệt là nếu một CHỌN đơn giản sẽ nhanh như vậy.

Phần kết luận:

  • CURRVAL khá vô dụng, vì nó không phát hiện NEXTVAL từ một phiên khác, nó chỉ trả về những gì bạn đã biết từ NEXTVAL trước đó của bạn
  • CHỌN MAX (...) TỪ ... là một giải pháp tốt, đơn giản và nhanh chóng, giả sử chuỗi của bạn được liên kết với bảng đó
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.