2010-10-19 5 views
51

मैं अपने आवेदन के लिए एक विन्यास तालिका में एक ही पंक्ति संग्रहीत करना चाहते हैं। मैं यह लागू करना चाहता हूं कि इस तालिका में केवल एक पंक्ति हो सकती है।एसक्यूएल सर्वर: एक पंक्ति को रखने के लिए तालिका को कैसे बाधित करें?

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

+0

नाम पर प्राथमिक कुंजी के साथ कॉलम '(नाम, मूल्य) 'वाली तालिका का उपयोग क्यों न करें। फिर आप 'तालिका से वैल्यू का चयन कर सकते हैं जहां नाम =?' निश्चित रूप से कि कोई भी पंक्ति या एक पंक्ति वापस नहीं की जाएगी। –

+1

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

+2

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

उत्तर

67

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

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

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

+1

+1। इस दृष्टिकोण सेल्को "सहायक के लिए एसक्यूएल" –

+0

में एक सहायक स्थिरांक तालिका के लिए उपयोग करता है यह जितना आसान हो उतना आसान है। धन्यवाद। – Martin

+0

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

4

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

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

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

+0

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

0
IF NOT EXISTS (select * from table) 
BEGIN 
    ///Your insert statement 
END 
1

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

11

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

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

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

(अपने डीबीएमएस स्वाद पर निर्भर करता है):

फिर, कृपया अपनी मौजूदा विन्यास प्राप्त करने के लिए, आप की तरह कुछ का उपयोग करें।

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

+0

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

+0

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

+0

अच्छा। बस 'शीर्ष 1 चुनें ... create_date_time द्वारा आदेश DESC' – Baodad

37

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

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') 
) 

जोड़ना "डिफ़ॉल्ट 'एक्स' ', आप लॉक से निपटने के लिए कभी नहीं होगा कॉलम, और याद रखना होगा कि पहली बार तालिका लोड करते समय लॉक वैल्यू कौन सा था। छात्र तालिका:: क्रमांक:

+3

+1 - अच्छी टिप, धन्यवाद। – Martin

+0

डिफ़ॉल्ट बाधा को भी नामित किया जाना चाहिए या अन्यथा इसे स्वत: उत्पन्न भ्रमित नाम मिलेगा। 'लॉक चार (1) नल कंसस्ट्रेंट डीएफ_T1_ लॉक डेफॉल्ट' एक्स 'नहीं –

0

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

2

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

2

यहां एक समाधान है जो मैं लॉक-टाइप टेबल के साथ आया था जिसमें केवल एक पंक्ति हो सकती है, जिसमें वाई या एन (उदाहरण के लिए एक एप्लिकेशन लॉक स्टेटस) हो।

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

सम्मिलित एक पंक्ति, "सामान्य" राज्य के साथ (जैसे एन बंद नहीं करने का मतलब है)

फिर तालिका केवल एक संकेत है कि पर एक सम्मिलित ट्रिगर बनाना (डीबी 2) या रेज़रर (एसक्यूएल सर्वर) या RAISE_APPLICATION_ERROR (ओरेकल)। इससे ऐसा होता है कि एप्लिकेशन कोड तालिका अपडेट कर सकता है, लेकिन कोई भी INSERT विफल हो जाता है।

डीबी 2 उदाहरण: मेरे लिए

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'; 

काम करता है।

0

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

CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL, 
[Config1] [nvarchar](max) NOT NULL, 
[Config2] [nvarchar](max) NOT NULL 
संबंधित मुद्दे