मेरे विचार से विचार करने के लिए दो मामले हैं:
- एक पंक्ति को स्थानांतरित करें ताकि यह क्रम में पहले दिखाई दे।
- एक पंक्ति को स्थानांतरित करें ताकि यह क्रम में बाद में दिखाई दे।
यह किसी भी तरह से गैर-तुच्छ है। यह स्पष्ट नहीं है कि कॉलम 'ऑर्डर' पर एक अद्वितीय बाधा है या नहीं; अंतिम परिणाम निश्चित रूप से एक अद्वितीय आदेश देने वाला माना जाता है।
संकेतन:
- 'चालू' पुराने मान में 'ऑर्डर =n' मान वाली पंक्ति को संदर्भित करता है
- 'Nn' नए मानों में 'order =n' वाली पंक्ति को दर्शाता है
उदाहरण में (केस 1 का उदाहरण):
- O3 --> N1
- O1 --> N2
- O2 --> N3
एक विकल्प के रूप में, मूविंग id =2 पर विचार करें ताकि इसका क्रम =4:
. हो- O2 --> N4
- O3 --> N2
- O4 --> N3
आप मूल रूप से 'अन्य' पंक्तियों में से एक को जोड़ या घटा रहे हैं, जहां वे पुराने क्रम में स्थानांतरित पंक्ति की पुरानी स्थिति और स्थानांतरित पंक्ति की नई स्थिति के बीच की पंक्तियाँ हैं। एक छद्म कोड में, स्थानांतरित पंक्ति के पहले और बाद की स्थिति की पहचान करने के लिए $old और $new का उपयोग करना, और केस 1 ($old> $new) से निपटना:
UPDATE AnonymousTable
SET order = CASE
WHEN order = $old THEN $new
WHEN order >= $new AND order < $old THEN order + 1
END CASE
WHERE order BETWEEN $new AND $old;
केस 2 के लिए संबंधित कोड ($old <$new) है:
UPDATE AnonymousTable
SET order = CASE
WHEN order = $old THEN $new
WHEN order > $new AND order <= $old THEN order - 1
END CASE
WHERE order BETWEEN $old AND $new;
समग्र रूप से अद्यतन पर WHERE क्लॉज को देखते हुए, आप केस में दूसरे WHEN को हटाने और इसे एक साधारण ELSE से बदलने में सक्षम हो सकते हैं।
UPDATE AnonymousTable
SET order = CASE
WHEN order = $old THEN $new
ELSE order + 1
END CASE
WHERE order BETWEEN $new AND $old;
UPDATE AnonymousTable
SET order = CASE
WHEN order = $old THEN $new
ELSE order - 1
END CASE
WHERE order BETWEEN $old AND $new;
मुझे लगता है कि एक संग्रहीत प्रक्रिया क्रम में है - इनपुट पैरामीटर $old, $new के आधार पर दो कथनों के बीच चयन करना। आप '($old - $new) / ABS($old - $new)
जैसे भावों के विवेकपूर्ण मिश्रण के साथ कुछ करने में सक्षम हो सकते हैं। ' और 'MIN($old, $new)
' और 'MAX($old, $new)
' जहां MIN/MAX समुच्चय नहीं हैं, लेकिन मूल्यों की एक जोड़ी के लिए तुलनित्र कार्य करता है (जैसा कि फोरट्रान में पाया जाता है, अन्य प्रोग्रामिंग भाषाओं के बीच)।
ध्यान दें कि मैं मान रहा हूं कि जब एक एकल SQL कथन निष्पादित हो रहा है, तो विशिष्टता बाधा (यदि कोई हो) लागू नहीं होती है क्योंकि प्रत्येक पंक्ति बदल जाती है - केवल जब कथन पूरा हो जाता है। यह आवश्यक है क्योंकि आप वास्तव में उस क्रम को नियंत्रित नहीं कर सकते हैं जिसमें पंक्तियों को संसाधित किया जाता है। मुझे डीबीएमएस के बारे में पता है जहां इससे परेशानी होगी; मैं दूसरों के बारे में जानता हूं जहां यह नहीं होगा।
यह सब एक एकल SQL कथन में किया जा सकता है - लेकिन आप चाहते हैं कि एक संग्रहीत कार्यविधि कथन के मापदंडों को क्रमबद्ध करे। मैं आईबीएम इनफॉर्मिक्स डायनेमिक सर्वर (मैकोज़ एक्स 10.6.2 पर 11.50.FC6) का उपयोग करता हूं, और यह डीबीएमएस में से एक है जो स्टेटमेंट के अंत में 'ऑर्डर' कॉलम पर अद्वितीय बाधा को लागू करता है। मैंने UNIQUE बाधा के बिना SQL का विकास किया; वह भी काम किया, बिल्कुल। (और हाँ, IDS आपको DDL स्टेटमेंट जैसे CREATE TABLE और CREATE PROCEDURE को वापस रोल करने की अनुमति देता है। आपने क्या कहा? आपका DBMS नहीं करता है? कितना विचित्र है!)
BEGIN WORK;
CREATE TABLE AnonymousTable
(
id INTEGER NOT NULL PRIMARY KEY,
title VARCHAR(10) NOT NULL,
order INTEGER NOT NULL UNIQUE
);
INSERT INTO AnonymousTable VALUES(1, 'test1', 1);
INSERT INTO AnonymousTable VALUES(2, 'test2', 2);
INSERT INTO AnonymousTable VALUES(3, 'test3', 3);
INSERT INTO AnonymousTable VALUES(4, 'test4', 4);
SELECT * FROM AnonymousTable ORDER BY order;
CREATE PROCEDURE move_old_to_new(old INTEGER, new INTEGER)
DEFINE v_min, v_max, v_gap, v_inc INTEGER;
IF old = new OR old IS NULL OR new IS NULL THEN
RETURN;
END IF;
LET v_min = old;
IF new < old THEN
LET v_min = new;
END IF;
LET v_max = old;
IF new > old THEN
LET v_max = new;
END IF;
LET v_gap = v_max - v_min + 1;
LET v_inc = (old - new) / (v_max - v_min);
UPDATE AnonymousTable
SET order = v_min + MOD(order - v_min + v_inc + v_gap, v_gap)
WHERE order BETWEEN v_min AND v_max;
END PROCEDURE;
EXECUTE PROCEDURE move_old_to_new(3,1);
SELECT * FROM AnonymousTable ORDER BY order;
EXECUTE PROCEDURE move_old_to_new(1,3);
SELECT * FROM AnonymousTable ORDER BY order;
INSERT INTO AnonymousTable VALUES(5, 'test5', 5);
INSERT INTO AnonymousTable VALUES(6, 'test6', 6);
INSERT INTO AnonymousTable VALUES(7, 'test7', 7);
INSERT INTO AnonymousTable VALUES(8, 'test8', 8);
EXECUTE PROCEDURE move_old_to_new(3,6);
SELECT * FROM AnonymousTable ORDER BY order;
EXECUTE PROCEDURE move_old_to_new(6,3);
SELECT * FROM AnonymousTable ORDER BY order;
EXECUTE PROCEDURE move_old_to_new(7,2);
SELECT * FROM AnonymousTable ORDER BY order;
EXECUTE PROCEDURE move_old_to_new(2,7);
SELECT * FROM AnonymousTable ORDER BY order;
ROLLBACK WORK;
संख्याओं के साथ संग्रहीत कार्यविधि के आह्वान के जोड़े हर बार मूल क्रम को बहाल करते हैं। स्पष्ट रूप से, मैं v_inc
. को फिर से परिभाषित कर सकता था परिवर्तनशील ताकि केवल ±1 होने के बजाय, यह 'LET v_inc = v_inc - v_min + v_gap;
था ' और फिर एमओडी अभिव्यक्ति सिर्फ 'MOD(order + v_inc, v_gap)
होगी '। मैंने जाँच नहीं की है कि यह ऋणात्मक संख्याओं के साथ काम करता है या नहीं।
MySQL या अन्य DBMS के अनुकूलन को पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है।