Cách tạo một cột xem KHÔNG ĐẦY ĐỦ


84

Tôi đang cố tạo một chế độ xem mà tôi muốn một cột chỉ đúng hoặc sai. Tuy nhiên, có vẻ như bất kể tôi làm gì, SQL Server (2008) tin rằng cột bit của tôi bằng cách nào đó có thể là rỗng.

Tôi có một bảng có tên "Sản phẩm" với cột "Trạng thái" INT, NULL. Trong một dạng xem, tôi muốn trả về một hàng cho mỗi hàng trong Sản phẩm, với cột BIT được đặt thành true nếu cột Product.Status bằng 3, nếu không thì trường bit sẽ là false.

SQL mẫu

SELECT CAST( CASE ISNULL(Status, 0)  
               WHEN 3 THEN 1  
               ELSE 0  
             END AS bit) AS HasStatus  
FROM dbo.Product  

Nếu tôi lưu truy vấn này dưới dạng một dạng xem và xem các cột trong Object Explorer, cột HasStatus được đặt thành BIT, NULL. Nhưng nó không bao giờ được NULL. Có một số thủ thuật SQL kỳ diệu mà tôi có thể sử dụng để buộc cột này trở thành NOT NULL.

Lưu ý rằng, nếu tôi xóa CAST()xung quanh CASE, cột được đặt chính xác thành NOT NULL, nhưng sau đó loại của cột được đặt thành INT, điều này không như tôi muốn. Tôi muốn nó được BIT. :-)

Câu trả lời:


150

Bạn có thể đạt được những gì bạn muốn bằng cách sắp xếp lại truy vấn của mình một chút. Bí quyết là bạn ISNULLphải ở bên ngoài trước khi SQL Server sẽ hiểu rằng giá trị kết quả không bao giờ có thể là NULL.

SELECT ISNULL(CAST(
    CASE Status
        WHEN 3 THEN 1  
        ELSE 0  
    END AS bit), 0) AS HasStatus  
FROM dbo.Product  

Một lý do mà tôi thực sự thấy điều này hữu ích là khi sử dụng ORM và bạn không muốn giá trị kết quả được ánh xạ thành kiểu nullable. Nó có thể làm cho mọi thứ trở nên dễ dàng hơn nếu ứng dụng của bạn thấy giá trị không bao giờ có thể là giá trị rỗng. Sau đó, bạn không phải viết mã để xử lý các trường hợp ngoại lệ rỗng, v.v.


@Gunder: đừng lo, thực ra nó hơi phức tạp. Điều này cũng hữu ích để sử dụng khi tạo cột bit được tính toán trong bảng và muốn kết quả không có giá trị rỗng.
RedFilter

8
Tôi cần một cái gì đó tương tự, và tôi thấy rằng COALESCE()đã không làm việc, bạn thực sự phải sử dụngISNULL()
EvilBob22

@ EvilBob22 Thật kỳ lạ, vì cả COALESCE và ISNULL đều có thể trả về NULL. Tôi đoán chỉ là một câu chuyện biên dịch.
RedFilter

1
Điều này, gấp một tỷ lần, để bắt EntityFramework suy ra một khóa mà bình thường sẽ không suy ra một khóa.
Erik


3

FYI, đối với những người gặp phải thông báo này, việc thêm ISNULL () xung quanh bên ngoài quá trình truyền / chuyển đổi có thể làm rối tung trình tối ưu hóa trên chế độ xem của bạn.

Chúng tôi đã có 2 bảng sử dụng cùng một giá trị như một khóa chỉ mục nhưng với các loại số chính xác khác nhau (tôi biết là xấu) và chế độ xem của chúng tôi đang kết hợp chúng để tạo ra kết quả cuối cùng. Nhưng mã phần mềm trung gian của chúng tôi đang tìm kiếm một loại dữ liệu cụ thể và chế độ xem có CONVERT () xung quanh cột được trả về

Tôi nhận thấy, như OP đã làm, rằng các bộ mô tả cột của kết quả xem đã xác định nó là nullable và tôi đang nghĩ Đó là khóa chính / ngoại trên 2 bảng; tại sao chúng ta muốn kết quả được định nghĩa là nullable?

Tôi đã tìm thấy bài đăng này, ném ISNULL () xung quanh cột và thì đấy - không thể null được nữa.

Vấn đề là hiệu suất của chế độ xem đã đi thẳng xuống bồn cầu khi một truy vấn được lọc trên cột đó.

Vì một số lý do, CONVERT () rõ ràng trên cột kết quả của chế độ xem đã không làm hỏng trình tối ưu hóa (dù sao thì nó vẫn phải làm điều đó vì các phân vùng khác nhau) nhưng việc thêm một trình bao bọc ISNULL () dư thừa đã làm được, đường.


Bạn có thể chỉ ra giải pháp cho cách đảm bảo / chỉ ra tính không null CONVERT()trong một ví dụ không?
HOẶC Người lập bản đồ

1
Xin chào HOẶC - xin lỗi tôi đã không thấy thông báo này trong một thời gian. Đây là một ví dụ. Nếu bạn có CONVERT (BIT, U.RETIRED), 0) AS Đã nghỉ hưu trong chế độ xem của bạn, chuyển nói một byte hoặc một cột int thành bit / bool, thì nó sẽ trở thành vô hiệu. Bạn có thể làm cho cột đó trong chế độ xem của mình không thể bị vô hiệu hóa bằng cách thay thế cột đó bằng ISNULL (CONVERT (BIT, U.RETIRED), 0) AS đã ngừng hoạt động. Nếu U.RETIRED không rỗng để bắt đầu, thì về mặt chức năng, nó không thay đổi bất cứ điều gì ngoại trừ cột trong dạng xem. CẢNH BÁO: ISNULL () có thể ảnh hưởng đến việc tối ưu hóa truy vấn và lựa chọn chỉ báo.
user1664043

-3

Tất cả những gì bạn có thể làm trong câu lệnh Chọn là kiểm soát dữ liệu mà công cụ cơ sở dữ liệu gửi cho bạn với tư cách là một ứng dụng khách. Câu lệnh select không ảnh hưởng đến cấu trúc của bảng bên dưới. Để sửa đổi cấu trúc bảng, bạn cần thực hiện một câu lệnh Alter Table.

  1. Trước tiên, hãy đảm bảo rằng hiện không có giá trị nào trong trường bit đó trong bảng
  2. Sau đó thực hiện câu lệnh ddl sau: Alter Table dbo.Product Alter column status bit not null

Nếu, otoh, tất cả những gì bạn đang cố gắng làm là kiểm soát đầu ra của chế độ xem, thì những gì bạn đang làm là đủ. Cú pháp của bạn sẽ đảm bảo rằng đầu ra của cột HasStatus trong tập kết quả dạng xem trên thực tế sẽ không bao giờ có giá trị rỗng. Nó sẽ luôn là giá trị bit = 1 hoặc giá trị bit = 0. Đừng lo lắng về những gì trình khám phá đối tượng nói ...


6
Tôi không muốn thay đổi cột của bảng. Cột được định nghĩa là một cột số nguyên, cho phép null. Điều này phù hợp với thông số kỹ thuật của chúng tôi. Nhưng tôi cần một dạng xem trả về một cột có trường bit, không thể là giá trị rỗng. Tôi biết nó không thể rỗng, cột phải KHÔNG ĐẦY ĐỦ để nó ánh xạ chính xác trong ORM của chúng ta.
René
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.