SQL Server tương đương với mệnh đề Oracle USING INDEX


9

Có SQL Server 2008 tương đương với mệnh đề USING INDEX trong Oracle không? Cụ thể cho việc xây dựng:

CREATE TABLE c(c1 INT, c2 INT);
CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;

Trong Tài liệu máy chủ Sql về các chỉ mục duy nhất, nó nêu rõ (nhấn mạnh thêm):

Các chỉ mục duy nhất được thực hiện theo các cách sau:

Ràng buộc chính hoặc ràng buộc UNIITE

Khi bạn tạo một ràng buộc PRIMARY KEY, một chỉ mục được nhóm duy nhất trên cột hoặc các cột sẽ tự động được tạo nếu chỉ mục cụm trên bảng chưa tồn tại và bạn không chỉ định một chỉ mục không bao gồm duy nhất . Cột khóa chính không thể cho phép các giá trị NULL.

Điều này dường như ngụ ý rằng có một cách chỉ định chỉ mục nào sẽ được sử dụng cho Khóa chính.


Chỉ cần xác định PK cùng với bảng. create table c (c1 int not null primary key, c2 int)
a_horse_with_no_name

Đó là phần "tạo PK sử dụng một chỉ mục có tên" mà tôi quan tâm.
nik

Không có cách nào để làm điều đó. Khóa chính là một ràng buộc và một chỉ mục. Trong những gì bạn đã cung cấp khóa chính theo mặc định sẽ là một chỉ mục được nhóm duy nhất. Điều này sẽ làm cho chỉ mục được xác định khác trùng lặp trừ khi bạn bao gồm cả c1 và c2 trong mệnh đề where.
Aaron

Câu trả lời:


7

Có SQL Server 2008 tương đương với mệnh đề USING INDEX trong Oracle không?

Không. Khi bạn tạo khóa chính hoặc ràng buộc duy nhất trong SQL Server, một chỉ mục duy nhất để hỗ trợ ràng buộc đó được tạo tự động, với cùng các khóa.

Điều này dường như ngụ ý rằng có một cách chỉ định chỉ mục nào sẽ được sử dụng cho Khóa chính.

Không. Tài liệu chỉ cố gắng giải thích liệu chỉ mục hỗ trợ tự động sẽ được tạo thành cụm hay không độc quyền, nếu bạn không chỉ định. Đó là từ khó hiểu, tôi đồng ý.

Để làm rõ, khi bạn thêm một ràng buộc khóa chính vào một bảng hiện có mà không thể hiện một ưu tiên, chỉ mục hỗ trợ sẽ được phân cụm nếu không có chỉ mục phân cụm có sẵn trên bảng. Chỉ số hỗ trợ sẽ được tạo ra như nonclustered nếu đã có một nhóm chỉ số

Bạn có thể yêu cầu cụ thể một khóa chính được nhóm hoặc không bao gồm bằng cách sử dụng: PRIMARY KEY CLUSTEREDhoặc PRIMARY KEY NONCLUSTERED.

Công bằng, tài liệu rõ ràng hơn nhiều về chủ đề tại:

bảng_constraint (Giao dịch-SQL)


5

Cú pháp SQL Server để tạo một chỉ mục cụm cũng là một khóa chính là:

CREATE TABLE dbo.c
(
    c1 INT NOT NULL, 
    c2 INT NOT NULL,
    CONSTRAINT PK_c
    PRIMARY KEY CLUSTERED (c1, c2)
);

Theo như nhận xét của bạn: "tạo PK sử dụng chỉ mục được đặt tên", đoạn mã trên sẽ dẫn đến chỉ mục khóa chính được đặt tên là "PK_c".

Khóa chính và khóa phân cụm không phải là cùng một cột. Bạn có thể định nghĩa chúng một cách riêng biệt. Trong ví dụ trên, thay đổi CLUSTEREDtừ khóa thành NONCLUSTERED, và sau đó chỉ cần thêm một chỉ mục được nhóm bằng CREATE INDEXcú pháp:

CREATE TABLE dbo.c
(
    c1 INT,
    c2 INT,
    CONSTRAINT PK_c
    PRIMARY KEY NONCLUSTERED (c1, c2)
);

CREATE CLUSTERED INDEX CX_c ON dbo.c (c2);

Trong SQL Server, chỉ mục được nhóm bảng, chúng là một và giống nhau. Một chỉ mục cụm xác định thứ tự logic của các hàng được lưu trữ trong bảng. Trong ví dụ đầu tiên của tôi, các hàng được lưu trữ theo thứ tự các giá trị của cột c1c2cột. Vì khóa phân cụm cũng được định nghĩa là khóa chính, nên sự kết hợp c1c2phải là toàn bảng duy nhất.

Trong ví dụ thứ hai, khóa chính bao gồm các cột c1c2cột, tuy nhiên khóa phân cụm chỉ là c2cột. Vì tôi không chỉ định UNIQUEthuộc tính trong CREATE INDEXcâu lệnh, khóa cluster ( c2) không bắt buộc phải là duy nhất trên bảng. Một "uniquifier" sẽ được SQL Server tự động tạo và gắn vào các giá trị trong c2cột để tạo khóa phân cụm. Khóa phân cụm này, vì nó là duy nhất, sau đó sẽ được sử dụng làm id hàng trong các chỉ mục khác được tạo trên bảng.

Để chứng minh khóa phân cụm điều khiển bố cục các hàng trong bộ lưu trữ, bạn có thể sử dụng chức năng không có giấy tờ , fn_PhysLocCracker(%%PHYSLOC%%). Đoạn mã sau cho thấy các hàng được đặt trên đĩa theo thứ tự của c2cột, mà tôi đã xác định là khóa phân cụm:

USE tempdb;

CREATE TABLE dbo.PKTest
(
    c1 INT NOT NULL
    , c2 INT NOT NULL
    , c3 VARCHAR(256) NOT NULL
);

ALTER TABLE PKTest 
ADD CONSTRAINT PK_PKTest 
PRIMARY KEY NONCLUSTERED (c1, c2);

CREATE CLUSTERED INDEX CX_PKTest 
ON dbo.PKTest(c2);

TRUNCATE TABLE dbo.PKTest;

INSERT INTO dbo.PKTest (c1, c2, c3)
SELECT TOP(25) o1.object_id / o2.object_id, o2.object_id, o1.name + '.' + o2.name
FROM sys.objects o1
    , sys.objects o2
WHERE o1.object_id >0 
    and o2.object_id > 0;

SELECT plc.file_id
    , plc.page_id
    , plc.slot_id
    , pk.*
FROM dbo.PKTest pk
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;

Các kết quả từ tempdb của tôi là:

nhập mô tả hình ảnh ở đây

Trong hình trên, ba cột đầu tiên được xuất ra từ fn_PhysLocCrackerhàm, hiển thị thứ tự vật lý của các hàng trên đĩa. Bạn có thể thấy slot_idgiá trị tăng bước khóa với c2giá trị, đó là khóa phân cụm. Chỉ mục khóa chính lưu trữ các hàng theo một thứ tự khác, có thể được nhìn thấy bằng cách buộc SQL Server trả về kết quả từ việc quét khóa chính:

SELECT pkt.c1
    , pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);

Lưu ý, tôi đã không sử dụng một ORDER BYmệnh đề trong tuyên bố trên vì tôi đang cố gắng hiển thị thứ tự của các mục trong chỉ mục khóa chính.

Đầu ra từ truy vấn trên là:

nhập mô tả hình ảnh ở đây

Nhìn vào fn_PhysLocCrackerhàm, chúng ta có thể thấy thứ tự vật lý của chỉ số khóa chính.

SELECT plc.file_id
    , plc.page_id
    , plc.slot_id
    , pkt.c1
    , pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN)
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;

Vì chúng tôi chỉ đọc từ chính chỉ mục, tức là không có cột nào bên ngoài chỉ mục được tham chiếu trong truy vấn, nên các %%PHYSLOC%%giá trị đại diện cho các trang trong chính chỉ mục.

Kết quả:

nhập mô tả hình ảnh ở đây

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.