ट्रिगर शायद आप चाहते हैं। हालांकि, इसे ठीक से और कुशलता से काम करना बदसूरत होगा। यदि आप पहले की तारीखों में बार-बार पंक्तियाँ डालने जा रहे हैं, तो शायद प्रत्येक पंक्ति में शेष राशि को संग्रहीत न करना बेहतर है; इसके बजाय, क्वेरी या विचारों का उपयोग करें संतुलन खोजने के लिए। किसी विशेष तिथि पर शेष राशि का पता लगाने के लिए, इसे पहले की तारीखों के लिए पंक्तियों के साथ जोड़ दें और शुद्ध जमा राशि को वर्तमान लेनदेन आईडी के आधार पर समूहित करें:
CREATE VIEW pettybalance
AS SELECT SUM(older.pc_in - older.pc_out) AS balance,
current.pc_id AS pc_id, -- foreign key
current.pc_date AS `date`
FROM pettycash AS current
JOIN pettycash AS older
ON current.pc_date > older.pc_date
OR (current.pc_date = older.pc_date AND current.pc_id >= older.pc_id)
GROUP BY current.pc_id
;
मैं older.pc_id
. को भी प्रतिबंधित करता हूं current.pc_id
. से कम होना चाहिए स्कीमा और शेष राशि की गणना से संबंधित अस्पष्टता को ठीक करने के लिए। pc_date
के बाद से अद्वितीय नहीं है, आप किसी दी गई तिथि के लिए एक से अधिक लेन-देन कर सकते हैं। यदि ऐसा है, तो प्रत्येक लेन-देन के लिए शेष राशि क्या होनी चाहिए? यहां हम मान लेते हैं कि बड़ी आईडी वाला लेन-देन छोटी आईडी वाले लेन-देन के बाद आता है लेकिन उसकी तारीख समान होती है। अधिक औपचारिक रूप से, हम ऑर्डरिंग का उपयोग करते हैं
ध्यान दें कि इस दृश्य में, हम>:
. के आधार पर ऑर्डर का उपयोग करते हैं
ट्रिगर्स को ठीक से काम करने की कोशिश करने के बाद, मैं अनुशंसा करने जा रहा हूं कि कोशिश भी न करें। डालने/अपडेट करते समय आंतरिक तालिका या पंक्ति लॉक के कारण, आपको शेष कॉलम को एक नई तालिका में ले जाना होगा, हालांकि यह बहुत कठिन नहीं है (नाम बदलें pettycash
pettytransactions
. के लिए , एक नया pettybalance (balance, pc_id)
बनाएं तालिका, और pettycash
. नामक एक दृश्य बनाएं pettytransactions
में शामिल होने की तुलना में और pettybalance
pc_id
. पर ) मुख्य समस्या यह है कि ट्रिगर बॉडी बनाई या अपडेट की गई प्रत्येक पंक्ति के लिए एक बार निष्पादित होती है, जिससे वे अविश्वसनीय रूप से अक्षम हो जाएंगे। एक विकल्प यह होगा कि एक संग्रहीत प्रक्रिया
बनाई जाए। कॉलम अपडेट करने के लिए, जिसे आप डालने या अपडेट करने के बाद कॉल कर सकते हैं। एक दृश्य की तुलना में संतुलन प्राप्त करते समय एक प्रक्रिया अधिक प्रदर्शनकारी होती है, लेकिन अधिक भंगुर होती है क्योंकि यह डेटाबेस को संभालने के बजाय शेष राशि को अपडेट करने के लिए प्रोग्रामर पर निर्भर करता है। दृश्य का उपयोग करना क्लीनर डिज़ाइन है।
DROP PROCEDURE IF EXISTS update_balance;
delimiter ;;
CREATE PROCEDURE update_balance (since DATETIME)
BEGIN
DECLARE sincebal DECIMAL(10,2);
SET sincebal = (
SELECT pc_bal
FROM pettycash AS pc
WHERE pc.pc_date < since
ORDER BY pc.pc_date DESC, pc.pc_id DESC LIMIT 1
);
IF ISNULL(sincebal) THEN
SET sincebal=0.0;
END IF;
UPDATE pettycash AS pc
SET pc_bal=(
SELECT sincebal+SUM(net)
FROM (
SELECT pc_id, pc_in - pc_out AS net, pc_date
FROM pettycash
WHERE since <= pc_date
) AS older
WHERE pc.pc_date > older.pc_date
OR (pc.pc_date = older.pc_date
AND pc.pc_id >= older.pc_id)
) WHERE pc.pc_date >= since;
END;;
delimiter ;
विषय से परे
वर्तमान स्कीमा के साथ एक समस्या Float
. का उपयोग है s मौद्रिक मूल्यों को संग्रहीत करने के लिए। फ़्लोटिंग पॉइंट नंबरों का प्रतिनिधित्व कैसे किया जाता है, आधार 10 में सटीक संख्याएं (यानी दोहराए जाने वाले दशमलव प्रतिनिधित्व नहीं हैं) हमेशा फ्लोट के रूप में सटीक नहीं होते हैं। उदाहरण के लिए, 0.01 (आधार 10 में) संग्रहीत होने पर 0.009999999776482582... या 0.0100000000000000002081668... के करीब होगा। यह वैसे ही है जैसे आधार 3 में 1/3 "0.1" है, लेकिन आधार 10 में 0.333333.... के बजाय Float
के बजाय , आपको Decimal
टाइप करें:
ALTER TABLE pettycash MODIFY pc_in DECIMAL(10,2);
ALTER TABLE pettycash MODIFY pc_out DECIMAL(10,2);
यदि किसी दृश्य का उपयोग कर रहे हैं, तो pettycash.pc_bal
drop छोड़ें . अगर pettycash.pc_bal
को अपडेट करने के लिए संग्रहित प्रक्रिया का उपयोग कर रहे हैं , इसे भी बदला जाना चाहिए।