2009-03-19 70 views
14

Trong Oracle có một cơ chế để tạo các số thứ tự, ví dụ:Trình tự Oracle nhưng sau đó trong MS SQL Server

CREATE SEQUENCE supplier_seq 

    MINVALUE 1 
    MAXVALUE 999999999999999999999999999 
    START WITH 1 
    INCREMENT BY 1 
    CACHE 20; 

Và sau đó thực hiện báo cáo kết quả

supplier_seq.nextval 

để lấy số thứ tự tiếp theo.

Bạn sẽ tạo cùng chức năng như thế nào trong MS SQL Server?

Chỉnh sửa: Tôi không tìm cách để tự động tạo khóa cho bản ghi bảng. Tôi cần phải tạo ra một giá trị duy nhất mà tôi có thể sử dụng như một ID (hợp lý) cho một quá trình. Vì vậy, tôi cần các chức năng chính xác mà Oracle cung cấp.

Trả lời

15

Không có kết quả khớp chính xác.

Tương đương là IDENTITY mà bạn có thể đặt làm kiểu dữ liệu trong khi tạo bảng. SQLSERVER sẽ tự động tạo một số thứ tự chạy trong khi chèn. Giá trị được chèn cuối cùng có thể đạt được bằng cách gọi SCOPE_IDENTITY() hoặc bằng cách tham khảo biến hệ thống @@ IDENTITY (như được Frans chỉ ra)

Nếu bạn cần tương đương chính xác, bạn cần tạo một bảng và sau đó viết một thủ tục để retun giá trị tiếp theo và các hoạt động khác. Xem Marks phản ứng về những cạm bẫy về điều này.

Chỉnh sửa:
Máy chủ SQL đã triển khai Trình tự tương tự như Oracle. Vui lòng tham khảo câu hỏi này để biết thêm chi tiết.

How would you implement sequences in Microsoft SQL Server?

+0

Tôi cần tương đương chính xác và việc sử dụng quy trình cũng là ý tưởng đầu tiên. Tôi đã tự hỏi nếu có một giải pháp 'tự nhiên' hơn cho điều này. – Raymond

+0

Bạn đã hết may mắn ở đây rồi. – Dheer

+1

Có vẻ như SQL Server 2012 đã giới thiệu các đối tượng SEQUENCE trên mỗi http://stackoverflow.com/questions/282943/how-would-you-implement-sequences-in-microsoft-sql-server và http://msdn.microsoft.com/ vi/us/library/ff878091.aspx – Loudenvier

5

đặt trường này thành trường Nhận dạng. Trường sẽ tự động nhận giá trị của nó. Bạn có thể lấy giá trị được chèn cuối cùng bằng cách gọi SCOPE_IDENTITY() hoặc bằng cách tham khảo biến hệ thống @@ IDENTITY

Chức năng SCOPE_IDENTITY() được ưu tiên.

3

Như DHeer cho biết, hoàn toàn không có kết quả khớp chính xác. Nếu bạn cố gắng xây dựng quy trình của riêng mình để thực hiện điều này, bạn sẽ luôn dừng ứng dụng của mình khỏi mở rộng quy mô.

Trình tự của Oracle có khả năng mở rộng cao.

OK, tôi lấy lại nhẹ. Nếu bạn thực sự sẵn sàng tập trung vào đồng thời và bạn sẵn sàng lấy số theo thứ tự như có thể với một chuỗi, bạn có cơ hội. Nhưng vì bạn dường như không quen với t-sql để bắt đầu, tôi sẽ bắt đầu tìm kiếm một số tùy chọn khác khi (chuyển một ứng dụng Oracle sang MSSS - là những gì bạn đang làm). GUID trong chức năng "nextval". Điều đó sẽ mở rộng.

Ồ và KHÔNG sử dụng bảng cho tất cả các giá trị, chỉ để duy trì giá trị tối đa của bạn trong bộ nhớ cache. Bạn sẽ phải khóa nó để đảm bảo bạn cung cấp cho các giá trị duy nhất và đây là nơi bạn sẽ ngừng mở rộng quy mô. Bạn sẽ phải tìm hiểu xem có cách nào để lưu trữ các giá trị trong bộ nhớ và truy cập có lập trình vào một số loại khóa ổ khóa nhẹ, không phải ổ khóa bảng.

+0

Có thể có những khoảng trống trong một chuỗi Oracle nhưng không đúng thứ tự? – tuinstoel

+0

Nó nằm ngay trong chuỗi DDL. ĐẶT HÀNG Chỉ định ORDER để đảm bảo rằng số thứ tự được tạo theo thứ tự yêu cầu. Điều khoản này hữu ích nếu bạn đang sử dụng các số thứ tự như dấu thời gian. Lệnh bảo đảm thường không quan trọng đối với các trình tự được sử dụng để tạo khóa chính. –

1

Tôi ước rằng SQL Server có tính năng này. Nó sẽ làm cho rất nhiều thứ dễ dàng hơn.

Đây là cách tôi đã giải quyết vấn đề này.

Tạo bảng có tên là tblIdentities. Trong bảng này, đặt một hàng với giá trị tối thiểu và tối đa của bạn và tần suất số Sequence sẽ được đặt lại. Cũng đặt tên của một bảng mới (gọi nó là tblMySeqNum). Làm điều này làm cho việc thêm các trình tạo số Sequence Number sau này khá dễ dàng.

tblMySeqNum có hai cột. ID (là một định danh int) và InsertDate (là một cột thời gian ngày với một giá trị mặc định của GetDate()).

Khi bạn cần số seq mới, hãy gọi một sproc chèn vào bảng này và sử dụng SCOPE_IDENTITY() để tạo danh tính. Hãy chắc chắn rằng bạn đã không vượt quá tối đa trong tblIdentities. Nếu bạn có sau đó trả lại một lỗi. Nếu không trả lại số thứ tự của bạn.

Bây giờ, để đặt lại và dọn dẹp. Có một công việc chạy thường xuyên khi cần thiết để kiểm tra tất cả các bảng được liệt kê trong tblIdentites (chỉ cần một cho bây giờ) để xem nếu họ cần phải được đặt lại. Nếu họ đã nhấn giá trị đặt lại hoặc thời gian, sau đó gọi DBCC IDENT RESEED trên tên của bảng được liệt kê trong hàng (tblMySeqNum trong ví dụ này). Đây cũng là thời điểm tốt để xóa các hàng thừa mà bạn không thực sự cần trong bảng đó.

KHÔNG làm sạch hoặc chèn sẵn trong sproc của bạn nhận dạng danh tính. Nếu bạn làm như vậy thì trình tạo số thứ tự của bạn sẽ không mở rộng tốt.

Như tôi đã nói, nó sẽ làm cho rất nhiều điều dễ dàng hơn của tính năng này là trong SQL Server, nhưng tôi đã thấy rằng công việc này xung quanh các chức năng khá tốt.

Vaccano

+0

Tình yêu khi tôi nhận được phiếu bầu xuống, nhưng cử tri quá hèn nhát để nói lý do tại sao họ bỏ phiếu .... – Vaccano

1

này có thể đã được trả lời trong một thời gian dài trước đây ... nhưng từ SQL 2005 trở đi bạn có thể sử dụng chức năng ROW_NUMBER ... một ví dụ sẽ là:

select ROW_NUMBER() OVER (ORDER BY productID) as DynamicRowNumber, xxxxxx,xxxxx 

Các OVER tuyên bố sử dụng ORDER BY cho khóa chính duy nhất trong trường hợp của tôi ...

Hy vọng điều này sẽ giúp ... không có bảng tạm thời hoặc tham gia lạ !!

6

Bản sắc là giải pháp tốt nhất và có khả năng mở rộng nhất, NHƯNG, nếu bạn cần một chuỗi không phải là int tăng dần, như 00A, 00B, 00C hoặc một chuỗi đặc biệt, có phương pháp tốt nhất thứ hai. Nếu được triển khai chính xác, nó sẽ cân bằng OK, nhưng nếu được triển khai thực hiện nghiêm trọng, nó sẽ cân nặng. Tôi ngần ngại giới thiệu nó, nhưng những gì bạn làm là:

  1. Bạn phải lưu trữ "giá trị tiếp theo" trong bảng. Bảng có thể là một bảng đơn giản, một hàng, một cột chỉ với giá trị đó. Nếu bạn có một vài chuỗi, họ có thể chia sẻ bảng, nhưng bạn có thể nhận được ít tranh chấp hơn bằng cách có các bảng riêng biệt cho mỗi bảng.
  2. Bạn cần phải viết một câu lệnh cập nhật đơn sẽ tăng giá trị đó thêm 1 khoảng thời gian. Bạn có thể đặt cập nhật trong một proc được lưu trữ để làm cho nó đơn giản để sử dụng và ngăn chặn lặp lại nó trong mã ở những nơi khác nhau.
  3. Sử dụng trình tự chính xác, sao cho nó sẽ mở rộng hợp lý (không, cũng như Identitiy :-) yêu cầu hai điều sau: a. câu lệnh cập nhật có một cú pháp đặc biệt được thực hiện cho vấn đề chính xác này, cả hai sẽ tăng và trả về giá trị trong một câu lệnh đơn; b. bạn phải tìm nạp giá trị từ chuỗi tùy chỉnh TRƯỚC KHI bắt đầu giao dịch và ngoài phạm vi giao dịch. Đó là một lý do Tỷ lệ nhận dạng - nó trả về một giá trị mới không phân biệt phạm vi giao dịch, cho bất kỳ nào đã cố gắng chèn nhưng không quay trở lại về lỗi. Điều đó có nghĩa là nó sẽ không chặn, và cũng có nghĩa là bạn sẽ có khoảng trống cho các giao dịch không thành công.

Cú pháp cập nhật đặc biệt thay đổi một chút theo phiên bản, nhưng ý chính là bạn thực hiện gán cho biến và cập nhật trong cùng một câu lệnh. Đối với năm 2008, Itzik Ben-Gan có giải pháp gọn gàng này: http://www.sqlmag.com/Articles/ArticleID/101339/101339.html?Ad=1

Các trường học cũ 2000 và phương pháp sau trông như thế này:

CẬP NHẬT SequenceTable SET @localVar = value = value + 5 - thay đổi đuôi kết thúc với logic gia tăng của bạn

Điều này sẽ tăng và trả lại cho bạn giá trị tiếp theo.

Nếu bạn hoàn toàn không thể có khoảng trống (chống lại yêu cầu đó :-) thì về mặt kỹ thuật có thể đặt bản cập nhật đó hoặc proc bên cạnh phần còn lại của bạn, nhưng bạn có một lượt truy cập đồng thời lớn như mọi lần chờ đợi trước một cam kết.

Tôi không thể nhận tín dụng về điều này; Tôi đã học được tất cả từ Itzik.

0

Không phải là câu trả lời chính xác, nhưng ngoài một số câu trả lời hiện

SCOPE_IDENTITY (Transact-SQL)

SCOPE_IDENTITY, IDENT_CURRENT và @@ IDENTITY là các hàm tương tự vì chúng trả về các giá trị ar e được chèn vào các cột nhận dạng.

IDENT_CURRENT không bị giới hạn bởi phạm vi và phiên; nó được giới hạn ở một bảng được chỉ định . IDENT_CURRENT trả về giá trị được tạo cho một bảng cụ thể trong bất kỳ phiên nào và bất kỳ phạm vi nào. Để biết thêm thông tin, hãy xem IDENT_CURRENT (Transact-SQL).

Nó có nghĩa là hai phiên khác nhau có thể có một giá trị bản sắc hoặc dãy số tương tự như vậy để tránh tình trạng này và nhận được số duy nhất cho tất cả các phiên sử dụng IDENT_CURRENT

0

Chính xác vì IDENT_CURRENT này không bị giới hạn bởi phạm vi và phiên ; nó được giới hạn trong một bảng được chỉ định. chúng tôi cần sử dụng SCOPE_IDENTITY() vì nhận diện phạm vi sẽ cung cấp cho chúng tôi số duy nhất được tạo trong phiên của chúng tôi và tính duy nhất được cung cấp bởi chính bản sắc.

1

Nếu bạn có thể cập nhật lên SQL Server 2012, bạn có thể sử dụng các đối tượng SEQUENCE. Ngay cả SQL Server 2012 Express cũng hỗ trợ cho chuỗi.

CREATE SEQUENCE supplier_seq 
    AS DECIMAL(38) 
    MINVALUE 1 
    MAXVALUE 999999999999999999999999999 
    START WITH 1 
    INCREMENT BY 1 
    CACHE 20; 

SELECT NEXT VALUE FOR supplier_seq 
SELECT NEXT VALUE FOR supplier_seq 
SELECT NEXT VALUE FOR supplier_seq 
SELECT NEXT VALUE FOR supplier_seq 
SELECT NEXT VALUE FOR supplier_seq 

Kết quả trong:

--------------------------------------- 
1 

(1 row(s) affected) 


--------------------------------------- 
2 

(1 row(s) affected) 


--------------------------------------- 
3 

(1 row(s) affected) 


--------------------------------------- 
4 

(1 row(s) affected) 


--------------------------------------- 
5 

(1 row(s) affected) 

Chỉ cần chăm sóc để xác định kiểu dữ liệu đúng. Nếu tôi không chỉ định nó, MAXVALUE bạn đã cung cấp sẽ không được chấp nhận, đó là lý do tại sao tôi đã sử dụng DECIMAL với độ chính xác cao nhất có thể.

Thông tin thêm về SEQUENCES tại đây: http://msdn.microsoft.com/en-us/library/ff878091.aspx

Các vấn đề liên quan