2010-02-24 32 views
65

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

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

Ví dụ SQL

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 như một cái nhìn và nhìn vào các cột trong Object Explorer, cột HasStatus được thiết lập để BIT, NULL. Nhưng nó không bao giờ là NULL. Có một số phép thuật SQL trick tôi có thể sử dụng để buộc cột này là NOT NULL.

Chú ý rằng, nếu tôi loại bỏ các CAST() quanh CASE, cột được thiết lập một cách chính xác như NOT NULL, nhưng sau đó loại của cột được thiết lập để INT, mà không phải là những gì tôi muốn. Tôi muốn nó là BIT. :-)

+0

@Gunder: +1, Chào mừng bạn đến với StackOverflow. Tôi đã định dạng câu hỏi của bạn, hãy xem nó để tìm hiểu về định dạng :) –

+0

Ahh, tôi cần thêm một ngắt dòng nữa trước mã. Cảm ơn. :-) –

Trả lời

119

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 bạn một chút. Bí quyết là ISNULL phả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 tôi thực sự thấy hữu ích khi sử dụng ORM và bạn không muốn giá trị kết quả được ánh xạ tới loại có thể vô hiệu. Nó có thể làm mọi thứ dễ dàng hơn nếu ứng dụng của bạn thấy giá trị không bao giờ có thể rỗng. Sau đó, bạn không phải viết mã để xử lý các ngoại lệ rỗng, v.v.

+0

Điều đó có hiệu quả! - Cảm ơn bạn rất nhiều! - Mặc dù tôi có một chút bối rối, rằng tôi đã không thử điều đó trước. :-) –

+0

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

+4

Tôi cần một cái gì đó tương tự, và tôi thấy rằng 'COALESCE()' không hoạt động, bạn thực sự * phải * sử dụng 'ISNULL()' – EvilBob22

-1

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 khách hàng. Câu lệnh chọn không có ả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 Bảng Alter.

  1. Trước tiên hãy chắc chắn rằng hiện tại chưa có null ở chỗ trường bit trong bảng
  2. Sau đó, thực hiện báo cáo kết quả ddl sau: Alter Table dbo.Product Alter column status bit not null

Nếu, OTOH, tất cả các bạn đang cố gắng làm là kiểm soát đầu ra của khung nhìn, sau đó 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 kết quả lượt xem sẽ thực tế là không bao giờ là là rỗng. Nó sẽ luôn luôn là một trong hai giá trị bit = 1 hoặc bit value = 0. Đừng lo lắng những gì đối tượng thám hiểm nói ...

+5

Tôi không muốn thay đổi cột của bảng. Cột được định nghĩa là cột số nguyên, cho phép null. Điều này phù hợp với thông số của chúng tôi. Nhưng tôi cần một khung nhìn trả về một cột với một trường bit, không thể rỗng. Nó không đủ mà tôi biết nó không thể được null, cột phải được NOT NULL, do đó nó sẽ bản đồ một cách chính xác trong ORM của chúng tôi. –

0

Đây là mã tôi sử dụng, nó sẽ làm cho cột ID NOT NULL và tất cả các NULL khác. Bạn phải đúc cột bit hoặc varchar, và so sánh cột int với NULL.

CREATE TABLE [dbo].[aTestTable](
    [ID] [int] NOT NULL, 
    [varcharCol] [varchar](50) NOT NULL, 
    [nullvarcharCol] [varchar](50) NULL, 
    [bitCol] [bit] NOT NULL, 
    [nullbitCol] [bit] NULL, 
    [intCol] [int] NOT NULL, 
    [nullintCol] [int] NULL, 
CONSTRAINT [PK_aTestTable] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 


CREATE VIEW [dbo].[aTestView] 
AS 
SELECT ID , 
     NULLIF(varcharCol , '') AS varcharCol , 
     NULLIF(CAST(varcharCol AS VARCHAR), null) AS varcharCol1, --better 
     nullvarcharCol , 
     NULLIF(CAST(bitCol AS INT), null) AS bitCol , 
     nullbitCol , 
     NULLIF(CAST(intCol AS INT), NULL) AS intCol , 
     nullintCol 
FROM dbo.aTestTable 


Sample Data: 

ID varcharCol nullvarcharCol bitCol nullbitCol intCol nullintCol 
1 1 1 1 1 1 1 
2 0 0 0 0 0 0 
3 0 NULL 0 NULL 0 NULL 
4 a a 1 1 2 2 

hth

3

FYI, cho những người chạy vào thông báo này, thêm ISNULL() xung quanh bên ngoài của dàn diễn viên/chuyển đổi có thể mess lên tôi ưu hoa trên quan điểm 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 độ chính xác số khác nhau (xấu, tôi biết) và quan điểm của chúng tôi đã tham gia vào 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ó một CONVERT() xung quanh cột trả về

Tôi nhận thấy, như OP đã làm, các mô tả cột của kết quả xem được xác định là rỗng và tôi đã suy nghĩ Đó là một khóa chính/nước 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ể vô hiệu nữa.

Vấn đề là hiệu suất của chế độ xem đã đi thẳng xuống nhà vệ sinh khi truy vấn được lọc trên cột đó. Vì lý do nào đó, một CONVERT rõ ràng() trên cột kết quả của khung nhìn không làm hỏng trình tối ưu hóa (nó sẽ phải làm điều đó vì các phần khác nhau) nhưng thêm một ISNULL() wrapper đã làm , trên con đường lớn.

+0

Bạn có thể hiển thị giải pháp cho cách đảm bảo/chỉ ra không nullability với 'CONVERT()' trong một ví dụ, xin vui lòng? –

+1

Xin chào O. R. - xin lỗi tôi đã không thấy điều 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, hãy chuyển nói một byte hoặc một cột int thành bit/bool, sau đó nó trở thành rỗng. Bạn có thể làm cho cột đó trong chế độ xem của bạn không thể rỗng bằng cách thay thế nó bằng ISNULL (CONVERT (BIT, U.RETIRED), 0) AS đã nghỉ hưu. Nếu U.RETIRED không phải là null để bắt đầu, nó có chức năng không thay đổi bất cứ điều gì ngoại trừ cột trong khung nhìn. CẢNH BÁO: ISNULL() có thể can thiệp vào tối ưu hóa truy vấn và lựa chọn các chỉ dẫn. – user1664043

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