क्यों नहीं एक पूर्ण गणना वाला कॉलम एक दृश्य में अशक्त माना जाता है?


15

मेरे पास एक टेबल है:

CREATE TABLE [dbo].[Realty](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [RankingBonus] [int] NOT NULL,
    [Ranking]  AS ([Id]+[RankingBonus]) PERSISTED NOT NULL
    ....
)

और एक दृश्य:

CREATE View  [dbo].[FilteredRealty] AS
 SELECT 
realty.Id as realtyId,
...
COALESCE(realty.Wgs84X, ruian_cobce.Wgs84X, ruian_obec.Wgs84X) as Wgs84X,
COALESCE(realty.Wgs84Y, ruian_cobce.Wgs84Y, ruian_obec.Wgs84Y) as Wgs84Y,
realty.Ranking,
...
FROM realty
JOIN Category ON realty.CategoryId = Category.Id
LEFT JOIN ruian_cobce ON realty.cobceId = ruian_cobce.cobce_kod
LEFT JOIN ruian_obec ON realty.obecId = ruian_obec.obec_kod
LEFT JOIN okres ON realty.okresId = okres.okres_kod
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND ExternFile.IsMain = 1
                     AND ExternFile.ForeignTable = 5
INNER JOIN Person ON realty.OwnerId = Person.Id
WHERE Person.ConfirmStatus = 1

मेरे पास C # (LinqToSQL) में एक dbml मॉडल है जिसमें फ़िल्टर किए गए दृश्य हैं। [रैंकिंग] क्षेत्र एक नल पूर्णांक के रूप में और इसलिए मैं जब मैं डेटाबेस में कुछ भी बदल हर बार उत्पन्न कोड में टाइप ठीक करने के लिए है मान्यता प्राप्त है। यह मेरे लिए बहुत निराशाजनक है और बहुत सारे मैनुअल काम हैं।

FilteredRealty ( इस संबंधित प्रश्न के बारे में ) में कोई समुच्चय नहीं हैं ।

यदि Realty.Ranking गैर- अशक्त है, तो दृश्य के रैंकिंग कॉलम को क्यों अशक्त माना जाता है?

जवाबों:


19

[Ranking]क्षेत्र एक गणना स्तंभ होने के कारण के रूप में "Nullable" दिखा रहा है। हां, इसे घोषित किया जाता है NOT NULL, लेकिन कंप्यूटेड कॉलम के लिए MSDN पृष्ठ के रूप में , डेटाबेस इंजन क्वेरी-टाइम पर उस निर्धारण को बदल सकता है:

डेटाबेस इंजन स्वचालित रूप से प्रयुक्त अभिव्यक्तियों के आधार पर गणना किए गए स्तंभों की अशक्तता को निर्धारित करता है। अधिकांश अभिव्यक्तियों के परिणाम को अशक्त माना जाता है, भले ही केवल अतुलनीय कॉलम मौजूद हों, क्योंकि संभव अंडरफ्लो या ओवरफ्लो, अशक्त परिणाम भी उत्पन्न करेगा। एक तालिका में किसी भी गणना किए गए कॉलम की अशक्तता की जांच करने के लिए AllowNull संपत्ति के साथ COLUMNPROPERTY फ़ंक्शन का उपयोग करें । एक अभिव्यक्ति जो अशक्त है उसे ISNULL ( check_expression , constant ) निर्दिष्ट करके एक अमानवीय में बदल दिया जा सकता है , जहाँ स्थिरांक किसी भी अशक्त परिणाम के लिए प्रतिस्थापित किया गया एक अमानवीय मान है।

तो, आइए देखें कि क्या यह सच है:

CREATE TABLE [dbo].[Realty](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [RankingBonus] [int] NOT NULL,
    [Ranking]  AS ([Id]+[RankingBonus]) PERSISTED NOT NULL
);
GO

EXEC sp_help 'dbo.Realty';
-- Ranking: Nullable = "no"

SELECT COLUMNPROPERTY(OBJECT_ID(N'dbo.Realty'), N'Ranking', 'AllowsNull') AS [AllowsNull?];
-- 0

SELECT * FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM dbo.Realty', '', NULL);
-- Ranking: is_nullable = 1  ==  :-(

अब देखते हैं कि क्या उनकी सलाह ISNULLकाम करती है:

SELECT * FROM sys.dm_exec_describe_first_result_set(
   N'SELECT Id, RankingBonus, ISNULL(Ranking, -99) AS [RealRanking] FROM dbo.Realty;',
   '',
   NULL);
-- RealRanking: is_nullable = 0

उनकी सलाह सटीक लगती है, इसलिए आइए गणना करने की कोशिश करें कि गणना किए गए कॉलम की परिभाषा:

ALTER TABLE dbo.Realty
  ADD [RankingFixed] AS (ISNULL(([Id]+[RankingBonus]), -99))
  PERSISTED NOT NULL;
GO

और अब हम फिर से गुणों की जांच करते हैं, लेकिन नए क्षेत्र के लिए:

EXEC sp_help 'dbo.Realty';
-- RankingFixed: Nullable = "no"

SELECT COLUMNPROPERTY(OBJECT_ID(N'dbo.Realty'),
                      N'RankingFixed',
                      'AllowsNull') AS [AllowsNullsNow?];
-- 0

यह अब तक सकारात्मक दिख रहा है, लेकिन यहां तक ​​कि मूल परिभाषा ने इन दोनों जांचों से "NOT NULL" की सूचना नहीं दी है। तो चलिए असली परीक्षा की कोशिश करते हैं - कैसे डेटाबेस इंजन रन-टाइम पर अशक्तता को निर्धारित करता है:

SELECT * FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM dbo.Realty', '', NULL);
-- RankingFixed: is_nullable = 0  ==  :-) WOO HOO!

13

यह गारंटी देने के लिए कि रैंकिंग कंप्यूटेड कॉलम अभिव्यक्ति किसी भी परिस्थिति में NULL नहीं लौटती है, आपको इसे ISNULLउपयुक्त डिफ़ॉल्ट मान के साथ लपेटना होगा । उदाहरण के लिए:

Ranking AS ISNULL(Id + RankingBonus, 0) PERSISTED NOT NULL

NOT NULLबाधा सुनिश्चित करता है मौजूदा मूल्य नहीं जब तालिका संशोधित किया गया है अशक्त, प्रभाव में टेबल और सत्र-स्तरीय सेटिंग के संदर्भ में है।

हालाँकि, जब कोई क्वेरी उस अभिव्यक्ति को संदर्भित करता है, तो SQL सर्वर के पास स्थायी मान (यदि सेटिंग्स मेल खाती हैं) का उपयोग करने या अभिव्यक्ति को नए सिरे से गणना करने के बीच एक विकल्प है।

उदाहरण के लिए, कुछ सत्र सेटिंग्स NULL लौटने के लिए अतिप्रवाह का कारण बन सकती हैं, इसलिए SQL सर्वर को इस संभावना के लिए खाता होना चाहिए। जब दृश्य के माध्यम से एक्सेस किया जाता है, तो SQL सर्वर संभावित रूप से NULL को वापस करते हुए कॉलम को सही तरीके से चिह्नित करता है।

ISNULLअभिव्यक्ति पर एक बाहरी का उपयोग करना एकमात्र समर्थित तरीका है जिसे आप चाहते हैं। का उपयोग करते हुए COALESCEकाम नहीं करेगा, उदाहरण के लिए।

डेमो:

CREATE TABLE dbo.T1
(
    c1 integer NOT NULL,
    c2 integer NOT NULL,
    c3 AS c1 + c2 PERSISTED NOT NULL
);
GO
CREATE VIEW dbo.V1
AS
SELECT T.c1,
       T.c2,
       T.c3
FROM dbo.T1 AS T;
GO
SELECT AllowsNull = COLUMNPROPERTY(OBJECT_ID(N'dbo.V1', N'V'), N'c3', 'AllowsNull');
GO
ALTER TABLE dbo.T1
DROP COLUMN c3;
GO
ALTER TABLE dbo.T1
ADD c3 AS ISNULL(c1 + c2, 0) PERSISTED NOT NULL;
GO
EXECUTE sys.sp_refreshsqlmodule
    @name = N'dbo.V1';
GO
SELECT AllowsNull = COLUMNPROPERTY(OBJECT_ID(N'dbo.V1', N'V'), N'c3', 'AllowsNull');
GO
DROP VIEW dbo.V1;
DROP TABLE dbo.T1;
GO

नोट करें sys.sp_refreshsqlmoduleक्योंकि आपका दृश्य स्कीमाबाउंड नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.