SQL सर्वर: किसी एकल पंक्ति को शामिल करने के लिए तालिका को कैसे विवश किया जाए?


81

मैं अपने एप्लिकेशन के लिए कॉन्फ़िगरेशन तालिका में एक एकल पंक्ति संग्रहीत करना चाहता हूं। मैं यह लागू करना चाहूंगा कि इस तालिका में केवल एक पंक्ति हो सकती है।

एकल पंक्ति बाधा को लागू करने का सबसे सरल तरीका क्या है?


(Name, Value)नाम पर प्राथमिक कुंजी वाले स्तंभों वाली तालिका का उपयोग क्यों न करें । तब आप select Value from Table where Name = ?निश्चितता के साथ कह सकते हैं कि या तो कोई पंक्ति या एक पंक्ति वापस नहीं होगी।
19'10

2
मुझे यकीन नहीं है कि sql यहां सबसे अच्छा समाधान है। हो सकता है कि कॉन्फ़िगरेशन के लिए एक सरल xml फ़ाइल अधिक उपयुक्त हो। मुझे लगता है कि विन्यास! डेटा और sql डेटा के लिए बनाया गया था।
रेमी बेगररेल

2
@ar - मैंने देखा है कि जब आप पढ़ने, कहने, एक पूर्णांक बनाने की उम्मीद कर रहे हैं तो बुरी तरह से गलत हो जाते हैं, और आपको मूल्य स्तंभ में कुछ बुरी तरह से स्वरूपित मान मिलता है।
डेमियन_इन_यूएनबेलिएवर

@Damien_The_Unbeliever ऐसा क्यों होगा? क्योंकि आपने किसी के लिए कोई मूल्य नहीं निर्दिष्ट किया है Name?
नौमेनन

1
@ नोमैनन - ध्यान दें कि मेरी टिप्पणी arएस टिप्पणी की प्रतिक्रिया थी । मुद्दा यह है, यदि आप केवल नाम / मूल्य जोड़े का भंडारण कर रहे हैं, तो मूल्य बहुत अच्छी तरह से स्ट्रिंग होना चाहिए, और आपको डेटाबेस में सत्यापन लागू करने का कोई साधन नहीं मिला है। जब आप प्रत्येक सेटिंग के लिए अलग कॉलम के साथ एकल-पंक्ति तालिका का उपयोग करते हैं (जैसा कि ओपी चाहता था) तो आप आसानी से चेक कॉन्फ़िगरेशन के माध्यम से प्रत्येक कॉन्फ़िगरेशन सेटिंग के लिए सत्यापन को लागू कर सकते हैं
Damien_The_Unbeliever

जवाबों:


97

आप यह सुनिश्चित करते हैं कि स्तंभों में से एक में केवल एक मान हो सकता है, और फिर प्राथमिक कुंजी (या एक विशिष्टता बाधा लागू) करें।

CREATE TABLE T1(
    Lock char(1) not null,
    /* Other columns */,
    constraint PK_T1 PRIMARY KEY (Lock),
    constraint CK_T1_Locked CHECK (Lock='X')
)

मेरे पास विभिन्न डेटाबेसों में इन तालिकाओं की एक संख्या है, जो ज्यादातर विन्यास के लिए है। यह जानते हुए भी बहुत अच्छा है कि अगर कॉन्फिग मद में एक इंट होना चाहिए, तो आप कभी भी डीबी से एक इंट पढ़ेंगे।


2
+1। यह "Cel for Smarties" में एक सहायक स्थिरांक तालिका के लिए Celko उपयोग दृष्टिकोण है
मार्टिन स्मिथ

यह लगभग उतना ही सरल है जितना कि यह मिलता है। धन्यवाद।
मार्टिन

+1: दिलचस्प समाधान। साझा करने के लिए धन्यवाद से पहले मैंने इसे नहीं देखा था। हमेशा रास्ता आसान, जब आप जानते हैं कि कैसे ....
जॉन सैंसोम

यहाँ पर सोचने के लिए एक अनुवर्ती प्रश्न है। इस तालिका की प्राथमिक कुंजी क्या है? :)
nvogel

2
@BZ - cdt के लिए आशुलिपि है comp.databases.theory, एक यूनेटनेट समूह (Google समूहों के माध्यम से दिखाई देता है) जो मैं मानता हूं कि मैंने हाल ही में बहुत कुछ नहीं पढ़ा है। यह एसक्यूएल की तुलना में रिलेशनल सिद्धांत के आसपास अधिक उन्मुख था - लेकिन मुझे पता चला कि डपोर्टस / एसक्यूएलवोगेल ने भी एक ही समूह को आवृत्त किया। टीटीएम थर्ड मेनिफेस्टो का संदर्भ था , जो एसक्यूएल के बजाय संबंधपरक सिद्धांत के बारे में एक अच्छी बात कर रहा है (फिर से)।
डेमियन_इन_अनबेलेवर

53

मैं आमतौर पर डेमियन के दृष्टिकोण का उपयोग करता हूं, जिसने हमेशा मेरे लिए महान काम किया है, लेकिन मैं एक चीज भी जोड़ता हूं:

CREATE TABLE T1(
    Lock char(1) not null DEFAULT 'X',
    /* Other columns */,
    constraint PK_T1 PRIMARY KEY (Lock),
    constraint CK_T1_Locked CHECK (Lock='X')
)

"DEFAULT 'X' को जोड़ने पर, आपको कभी भी लॉक कॉलम से निपटना नहीं पड़ेगा, और यह याद नहीं रखना होगा कि पहली बार टेबल लोड करते समय लॉक का मान क्या था।


4
डिफ़ॉल्ट बाधा का भी नाम दिया जाना चाहिए अन्यथा उसे एक स्वतः स्फूर्त भ्रमित नाम मिल जाएगा। Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
डेविड एस।

1
इसके अलावा, आपको अपने डिफ़ॉल्ट मान को 'X' के अलावा कुछ और बनाना चाहिए। अगर मैं दूसरी पंक्ति डालने का प्रयास करता हूं तो मैंने अपनी लंबी स्ट्रिंग बना ली है, और यह मेरा त्रुटि संदेश है: प्राथमिक कुंजी बाधा 'PK_RestrictToOneRow' का उल्लंघन। डुप्लिकेट कुंजी को 'dbo.1ROWTABLE' ऑब्जेक्ट में सम्मिलित नहीं किया जा सकता। डुप्लिकेट कुंजी मान है (यह तालिका एक पंक्ति में बंद है)।
ज्योफ ग्रिसवल्ड

14

आप इस रणनीति पर पुनर्विचार करना चाहते हैं। इसी तरह की स्थितियों में, मैंने अक्सर ऐतिहासिक जानकारी के लिए आस-पास पड़ी पुरानी विन्यास पंक्तियों को छोड़ना अमूल्य पाया है।

ऐसा करने के लिए, आपके पास वास्तव में एक अतिरिक्त स्तंभ creation_date_time(प्रविष्टि / अद्यतन की तारीख / समय) और एक सम्मिलित या सम्मिलित / अद्यतन ट्रिगर है जो इसे वर्तमान तिथि / समय के साथ सही ढंग से आबाद करेगा।

फिर, अपना वर्तमान कॉन्फ़िगरेशन प्राप्त करने के लिए, आप कुछ इस तरह का उपयोग करते हैं:

select * from config_table order by creation_date_time desc fetch first row only

(आपके DBMS स्वाद पर निर्भर करता है)।

इस तरह, आप अभी भी पुनर्प्राप्ति उद्देश्यों के लिए इतिहास को बनाए रखने के लिए प्राप्त कर सकते हैं (यदि तालिका बहुत बड़ी हो जाती है तो आप क्लीनअप प्रक्रियाओं को संस्थापित कर सकते हैं लेकिन यह संभावना नहीं है) और आपको अभी भी नवीनतम कॉन्फ़िगरेशन के साथ काम करना है।


+1: मैं सुनता हूं कि आप क्या कह रहे हैं, लेकिन मैं अलग ऑडिट टेबल में बदलाव के इतिहास को रिकॉर्ड करना पसंद करता हूं।
मार्टिन

+1: ऑडिट ट्रेल लागू करने का दिलचस्प विचार साझा करने के लिए।
जॉन सैंसोम

अच्छा लगा। बसSELECT TOP 1 ... ORDER BY creation_date_time DESC
Baodad

5

आप डेटाबेस के भीतर इस प्रकार के व्यावसायिक तर्क को लागू करने के लिए ट्रिगर का INSTEAD लागू कर सकते हैं ।

ट्रिगर में यह जांचने के लिए तर्क हो सकता है कि क्या रिकॉर्ड पहले से ही तालिका में मौजूद है और यदि ऐसा है, तो सम्मिलित करें।

अब, बड़ी तस्वीर को देखने के लिए एक कदम वापस लेते हुए, मुझे आश्चर्य है कि क्या शायद आपके लिए इस जानकारी को संग्रहीत करने के लिए एक वैकल्पिक और अधिक उपयुक्त तरीका है, शायद एक कॉन्फ़िगरेशन फ़ाइल या उदाहरण के लिए पर्यावरण चर में?


+1 - मैं देख सकता हूं कि ट्रिगर कैसे काम करेगा, और शायद मैं उस दृष्टिकोण पर वापस आऊंगा, लेकिन मुझे डेमियन के सरल अवरोध पसंद हैं। एक दिलचस्प चर्चा है कि कॉन्फ़िगरेशन फ़ाइल में किस प्रकार का कॉन्फ़िगरेशन डेटा है और DB में क्या है। इस मामले में मुझे लगता है कि डीबी सही जगह है। इसमें कोई शक नहीं कि मुझे इस पर पछतावा होगा ... :-)
मार्टिन

2

मैं IsActive नाम के साथ प्राथमिक कुंजी के लिए एक बिट फ़ील्ड का उपयोग करता हूं। तो अधिकतम 2 पंक्तियाँ हो सकती हैं और मान्य पंक्ति प्राप्त करने के लिए sql है: सेटिंग्स से * का चयन करें जहाँ IsActive = 1 यदि तालिका का नाम सेटिंग्स है।


2

यहाँ एक समाधान है जो मैं एक लॉक-प्रकार तालिका के लिए आया था जिसमें केवल एक पंक्ति हो सकती है, Y या N (उदाहरण के लिए एक एप्लिकेशन लॉक स्टेट) को पकड़े हुए।

एक कॉलम के साथ तालिका बनाएं। मैंने एक कॉलम पर एक चेक बाधा डाल दी ताकि केवल एक वाई या एन को इसमें रखा जा सके। (या / या 0, या जो भी)

"सामान्य" स्थिति के साथ तालिका में एक पंक्ति सम्मिलित करें (जैसे N का अर्थ लॉक नहीं है)

फिर उस तालिका पर एक INSERT ट्रिगर बनाएं जिसमें केवल एक SIGNAL (DB2) या RAISERROR (SQL सर्वर) या RAISE_APPLICATION_ERROR (Oracle) हो। इससे ऐसा होता है कि एप्लिकेशन कोड तालिका को अपडेट कर सकता है, लेकिन कोई भी INSERT विफल रहता है।

DB2 उदाहरण:

create table PRICE_LIST_LOCK
(
    LOCKED_YN       char(1)   not null  
        constraint PRICE_LIST_LOCK_YN_CK  check (LOCKED_YN in ('Y', 'N') )
);
--- do this insert when creating the table
insert into PRICE_LIST_LOCK
values ('N');

--- once there is one row in the table, create this trigger
CREATE TRIGGER ONLY_ONE_ROW_IN_PRICE_LIST_LOCK
   NO CASCADE 
   BEFORE INSERT ON PRICE_LIST_LOCK
   FOR EACH ROW
   SIGNAL SQLSTATE '81000'  -- arbitrary user-defined value
     SET MESSAGE_TEXT='Only one row is allowed in this table';

मेरे लिये कार्य करता है।


2

पुराना प्रश्न लेकिन एक छोटे कॉलम प्रकार की पहचान (MAX, 1) का उपयोग कैसे करें?

CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL

आप SET IDENTITY_INSERT का उपयोग करके दूसरी पंक्ति जोड़ सकते हैं।
रज़वान सोकोल

1

आप तालिका पर सम्मिलित कार्रवाई पर एक ट्रिगर लिख सकते हैं। जब भी कोई तालिका में एक नई पंक्ति सम्मिलित करने का प्रयास करता है, तो सम्मिलित ट्रिगर कोड में नवीनतम पंक्ति को हटाने के तर्क को दूर करें।



-1

यहां हम एक अदृश्य मान भी बना सकते हैं जो डेटाबेस में पहली प्रविष्टि के बाद समान होगा। उदाहरण: छात्र तालिका: Id: int firstname: char यहां प्रवेश बॉक्स में, हमें आईडी कॉलम के लिए समान मान निर्दिष्ट करना होगा जो प्रतिबंधित होगा प्राथमिक कुंजी बाधा के कारण लॉक ब्ला ब्ला लिखने के अलावा पहली प्रविष्टि के बाद इस प्रकार हमेशा के लिए केवल एक पंक्ति होने के बाद। उम्मीद है की यह मदद करेगा!

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