JB-dagi yozuvlarni buyurtma qilish qobiliyati qanday?

Yozuvlarni qayta tartibga solish, JB-ni saqlash uchun qobiliyatni yaratish kerak (MS SQL-dan foydalanaman, lekin bu hech qanday ahamiyatga ega emas). Men mumkin bo'lgan 2 ta echimni ko'raman:

  1. Buyurtma ustuni qo'shing. So'ngra 2 yozuvni qayta tartiblashtirishni istasak, bu 2 ta yozuvlar uchun Buyurtma ustunini o'zgartirishimiz kerak. Birinchi yozuvning qiymati ikkinchi va teskarisiga o'rnatiladi. Muammo - biz buyurtma ustuniga noyob taqiqlashni qo'shishimiz kerak va biz buni oson qila olmaymiz, chunki birinchi qadamda quyidagicha xatoga yo'l qo'yamiz:

{"UNIQUE KEY cheklovini buzish" IX_EscortItems ".   'dbo.EscortItems' ob'ektida ikki nusxadagi kalit. Ikki nusxadagi kalit qiymati   (2, 20). \ R \ nBu bayonot bekor qilindi. "}}

  1. Ikkinchi yondashuv bir-biriga bog'langan ro'yxatdir. Ustun ota-onani qo'shsangiz, avvalgi elementning birinchi elementi yoki Id uchun null qiymatni saqlang. Lekin bizda noyob cheklov bilan bir xil muammo bor.

Ushbu muammoni hal qilish uchun to'g'ri yondashuv nima?

1
qo'shib qo'ydi muallif Schroeder, manba
Buyurtmaning maqsadi nima va qanday reordering kerak? Iltimos, haqiqiy foydalanish holatingizni ta'riflang. Sizning savolingizga ko'ra, reordering barcha qaydlar uchun bir vaqtning o'zida yoki svoplar yoki qo'shimchalar bilan amalga oshiriladimi yoki dasturingiz uchun noyob cheklovga ega bo'lishi uchun nega muhimligi aniq emas. Buyurtma ustuni (va "men buni dars kitobimdan bilib oldim" yetarli sabab emas!).
qo'shib qo'ydi muallif Peter LeFanu Lumsdaine, manba
-1 va ochiq ovoz berishni yoqish uchun ovoz berish, sizda savollarimga javob berish uchun etarli vaqt bor edi.
qo'shib qo'ydi muallif Peter LeFanu Lumsdaine, manba

8 javoblar

Siz foydalanishingiz mumkin bo'lgan bir nechta yondashuvlar mavjud:

  1. The easiest one is to forgo the UNIQUE constraint on the column that specifies the ordering (either as linked list or as sequence number). It is then up to the software to ensure that eventually the database is consistent again.
  2. Use sequence numbers with gaps.
    If you initially start with sequence numbers like 10, 20, 30, etc., then you can re-order them by allocating sequence numbers in-between the ones already given out.

    For example, to put the fourth element between the first and second, the sequence numbers would become 10, 15, 20, 30, 50, etc.

    To avoid running out of gaps to place elements, you can either periodically normalize the sequence numbers, or you can use floating point sequence numbers.

4
qo'shib qo'ydi
@ user285336: Agar siz bo'shliqlardan foydalansangiz (va har doim bo'sh joy qolsa), hech qachon ikkita elementni bitta buyurtma raqami berishga hojat yo'q. Hatto vaqtinchalik emas, shuning uchun UNIQUE cheklovlarni saqlab qolishingiz mumkin.
qo'shib qo'ydi muallif Dee, manba
Men bo'shliqlar haqida tushundim va bu naqshni qo'lladim (10-qadam bilan). Biroq, eng katta muammo UNIKQ cheklovdir. Albatta, bu haqda unutgan bo'lardim, lekin bu noto'g'ri. JB barcha zarur cheklovlarga ega bo'lishi kerak
qo'shib qo'ydi muallif CarLaTeX, manba

Siz uchun to'rtta variant. Variantni 4 yaxshi ko'raman, lekin birinchi narsa oson.

Variant 1. Faqat birgina yuqoriga chiqing

Order ustunidagi qiymatlar faqat ularning nisbiy qiymatlari ahamiyatga ega emas. Agar siz 1 dan 10, 11 dan 20 gacha, yoki 57 dan 66 gacha bo'lgan qatorlarni hisoblasangiz, barchasi bir xil.

Shunday qilib, juda sodda yechim faqat eng yuqori Order ustunidan yuqoriroq boshlashdir: sizning satringizda Buyurtma qiymatlari 1dan 10gacha bo'lsa va siz ularni qayta tiklashingiz kerak bo'lsa, ularga 20 dan 11 gacha qiymatlarni belgilash.

Ular to'g'ri tartiblashni tugatadilar va siz alohida qadriyatlarga ega bo'lmaguningiz uchun yagona qoidabuzarliklarga ega bo'lmaysiz.

Buning past tomoni butun ro'yxatni qayta tiklashni xohlamasangiz va faqat ikkita qiymatni almashtirishni xohlasangiz, bu biroz qiyin.

Varian-2. Unifikatsiyalangan cheklovda tartiblangan versiya raqamini kiriting

Order bitta ustun qo'shish o'rniga ikkita, SortOrder va SortVersion qo'shing. Bu ikki ustunning birikmasiga yagonalik cheklovini qo'llang.

Ro'yxatdagi elementlarni qayta buyurtma qilishni xohlasangiz, SortVersion uchun yangi qiymatni saqlaganingizda SortVersion ustunini bir marta oshiring.

Varian-r 3. Qatorlarni o'chiring va ularni qayta joylang

Foydalanadigan ramkaga qarab, bu eng qulay variant bo'lishi mumkin, chunki siz domen obyektlari sifatida ilovalar darajasida saqlangan yozuvlarga ega bo'lasiz. Faqat ularni o'chiring va kerakli tartibda ularni qayta joylang.

Agar EF dan foydalanmasangiz yoki FK munosabatlariga ega bo'lsangiz, bu tasodifiy o'chirishga olib kelishi mumkin.

Variant 4. "Buyurtma by" ustunidan alohida jadvalda saqlang

Texnik jihatdan bu eng moslashtirilgan variantdir, chunki tartiblash tartibi, ehtimol, korxonaning sifati emas, balki uning o'rniga shaxs va boshqa bir shaxs o'rtasidagi munosabatlarning atributidir. Shunday qilib, Sifat aslida 3NFni buzadi, ishonasizmi yoki yo'qmi - ustunlar qiymatlari kalit (1NF), barcha kalit (2NF) va boshqa narsa emas, balki (3NF) va bu holda Order ustuni, ob'ektning kontekstiga katta kontekstga bog'liq. Buni tartibga solish uchun birlashtirilgan stolga ega bo'lishingiz kerak.

Keling, bir faktura jadvali va line_item jadvali borligini aytaylik. InvoiceID , LineItemID va SortOrder o'z ichiga olgan invoice_line_item jadvalining uchinchi jadvalini qo'shing. Agar siz satrlarni buyurtma qilishni xohlasangiz, barchasini o'chiring, so'ngra ularni qayta joylang. Bu FK yoki tegishli narsalar bilan bog'liq har qanday muammolarni chetlab o'tadi, chunki bu FK-lar bu uchinchi stolda emas, balki boshqa stollardan birida bo'lishi kerak. Bu satr elementlari va fakturalar o'rtasidagi munosabatni o'zgartiradi, shuning uchun ularni o'chirish va o'zgartirish mantiqan. Tabiiyki, siz bittagina narsalarni birlashtirasiz.

4
qo'shib qo'ydi

Noyob taqiqlash ustun jadvalga va buyurtma ustunining tashqi kaliti bo'lishi kerak. Masalan, "Savatga savatni" ishlataman.

Table: ShoppingCartItems
- ShoppingCartId (FK to ShoppingCarts table)
- DisplayNumber (int)

Bunday holatda, noyob taqiqlash ShoppingCartItems.ShoppingCartId va ShoppingCartItems.DisplayNumber kombinatsiyasini jadvalda noyobligini ta'minlaydi - xarid qilish vositasi bir nechta element shu bilan bir xil displey buyrug'iga ega.

3
qo'shib qo'ydi
@BartvanIngenSchenau: Mening javobimni tuzatdim. Men "asosiy kalit" deb yozganman va "chet el kalit" deb o'ylayman. Sheesh. Bu o'sha kunlardan biri edi.
qo'shib qo'ydi muallif DenNukem, manba
Agar Items.Id birlamchi kalit bo'lsa, undagi va boshqa ustunlarning birikmasi noyobdir, chunki asosiy kalit faqatgina noyobdir.
qo'shib qo'ydi muallif Dee, manba

Temp uchun salbiy foydalanayapman

declare int @rowA = 7 
declare int @rowB = 22

update table set order = [email protected] where order =  @rowA; 
update table set order =  @rowA where order =  @rowB; 
update table set order =  @rowB where order = [email protected];

Siz uni bitimga joylashtirishingiz mumkin, lekin ko'pincha siz nizolarni keltira olmaysiz

3
qo'shib qo'ydi
Men pastga tushmadim, lekin boshqa mijozlar vaqtinchalik qatorni ko'rishga yo'l qo'ymaslik uchun operatsiyani bajarishim kerak.
qo'shib qo'ydi muallif svec, manba
Ovoz berish muammosi nima?
qo'shib qo'ydi muallif Flamewires, manba

Ko'pincha buyurtma ustunidan foydalanganda, muhim ahamiyatga ega bo'lgan buyruqlar emas. Shuning uchun siz buyurtma ustunidan foydalansangiz, ular bir-biriga nisbatan to'g'ri tartiblangan bo'lguncha raqamlardagi narsalarga e'tibor berishingiz shart emas.

Shunday qilib, rekordni tartibda ko'chirishni xohlasangiz, unda siz:

  • Kirish nuqtasida barcha buyurtma qiymatlarini oshiring va ochiq holda
  • yaratishingiz mumkin
  • rekordning buyurtma qiymatini ushbu uyaga yangilash.

Hech qanday nizolar

Keyinchalik tasvirlangan. Buyurtma qiymatlari bo'lsa:

1,2,3,4,5,6,7,8

va siz # 7-dagi elementni # 3-ga ko'chirishni xohlasangiz, avval siz kabi yangilanishni ishga tushirasiz

update foo set order = order +1 where container = X and order >=3

Bu sizga beradi

1,2,4,5,6,7,8,9

Keyin ko'chirmoqchi bo'lgan muayyan elementning buyurtma qiymatini belgilang

update foo set order = 3 where id = 102334

Va siz bilan tugashingiz mumkin

1,2,3,4,5,6,7,9

Siz boshqa reja tuzish turlari uchun o'xshash naqshga amal qilasiz.

Bu sizga engil yoki o'rta o'lchamli to'siqlar bilan ishlayotganingizda eng yaxshi ishlaydi. Agar sizda aniq buyurtma bilan 15 000 000 ta yozuv mavjud bo'lsa, ehtimol boshqa yondashuvlardan birini qo'llashni xohlaysiz.

2
qo'shib qo'ydi

Bu siz talablarni chuqurroq qazishingiz va amalga oshirish haqida juda ko'p tashvishlanmaslik kerak. U o'z-o'zidan g'amxo'rlik qiladi. Uni qilishning eng yaxshi usuli yo'q.

Tartiblash uchun noyob raqamlar mavjudmi, agar kimdir haqiqatdan g'amxo'rlik qilyaptimi? Agar foydalanuvchi sifatida men buni qo'lda bajarayotgan deb hisoblasam, ularning barchasi nolga o'xshamaydi. Agar tasodufiy duplikatni o'z ichiga oladigan deb hisoblasangiz va ular buyurtma ularning interfeysida nima ko'rayotganiga mos bo'lsa, har doim ogohlantirishni yuborishingiz mumkin. Shunga qaramay, bu noyob va tartiblangan raqamlar uchun faturalama tizimida talab mavjudmi (Germaniyadagi firma uchun ushbu raqamlardagi bo'shliqlarga yo'l qo'ymaslik uchun tizimda ishlashni eslayman)?

Agar tartiblashtirishni amalga oshirish uchun juda murakkab va vaqt sarflaydigan algoritm bo'lsa va ushbu qiymatni ishlash maqsadlari uchun saqlamoqchi bo'lsangiz, nega JBdagi biron bir cheklov bilan shug'ullanishingiz kerak? Kodni boshqaring.

Foydalanuvchilarga ochiladigan ro'yxatlar bo'yicha tartiblashni o'rnatish imkonini beruvchi tizim bilan ishlayman. Administrator raqamlarni belgilaydi va siz uni ishlaysiz. Replikatsiya uchun ta'qib qilish faqat bunga loyiq emas.

2
qo'shib qo'ydi

Umuman, relsli ma'lumotlar bazalari asosiy g'oyasining bir qismi, yozuvlar o'zida 1 da ma'lumotlar bazasida "xos" tartibga ega emas.

Buyurtma odatda so'rov natijalari asosida amalga oshiriladi. Bunday holatda, qaysi ustunlar ko'rsatilgan elementlarni ko'rsatilishini ko'rsatadigan tartibni belgilab olsak va natija shunga mos ravishda buyurtma berish haqida qaror qabul qilishimiz mumkin.

Misol uchun, buyurtmalar haqida hisobotlarni har bir buyurtmaning sana va vaqtiga ko'ra (masalan, ular joylashtirilgan tartibda ko'rsatishi) mumkin:

select ID, value, date /* , ... */ from Orders
order by ship_date

... yoki buyurtma yuborilgan sana/vaqt,

select ID, value, date /* , ... */ from Orders
order by ship_date

... yoki kattaligi bo'yicha buyurtmaning kamayishi ehtimoli bor (shuning uchun biz qachon sodir bo'lganligidan qat'iy nazar eng buyurtmalarni tezda ko'ra olamiz).

select ID, value, date /* , ... */ from Orders
order by value desc

Siz, albatta, buyurtmalarni butunlay o'zboshimchalik bilan namoyish qilishni xohlasangiz (yoki hech bo'lmaganda, bu mezonlarga asoslangan holda) istalgan paytda/ order_by ustuni (agar xohlasangiz, boshqa nom bilan) qo'sha olasiz. ma'lumotlar bazasida saqlanmaydi). Bunday holda, tartibni o'zgartirishni xohlasangiz, sizda bir nechta variant mavjud. Birinchidan, ma'lumotlar bazasiga ushbu ustun noyob qadriyatlarga ega ekanligini aytmaslikdir. Ikkinchidan, takroriylikni oldini olish. Sizning misolingiz uchun siz 1 va 2-sonli raqamlar bilan boshladingiz. Ularni almashtirish uchun raqamlarni mos ravishda 4 va 3-gacha o'zgartirishingiz mumkin.

Buni dasturiy jihatdan bajarish uchun 2 ustunidagi eng katta qiymatni topasiz, keyin buyurtma paytida asosiy qiymatdan biri katta qiymatdan foydalanasiz. Siz foydalanayotgan minimal qiymatni ham tekshirishni xohlashingiz mumkin. Yozuvlar sonidan kattaroq bo'lsa, siz raqamdan 0-dan boshlashingiz mumkin.


1. MS SQL-da "kümelenmiş katalog" kontseptsiyasi mavjud bo'lsa-da, bu qaydlar to'g'ridan-to'g'ri yozuvlar saqlanadigan tartib bilan bog'liq - bu asosan optimallashtirishdir. 2. Siz odatda bu ustunni indeksatsiya qilasiz, shuning uchun bu operatsiyani biz juda tez bajarishimiz mumkin.

2
qo'shib qo'ydi
@JohnKugelman: Savolning mazmuniga asoslanib, asosiy ma'lumotni yopish uchun keraksiz deb hisoblamayman. Aksincha, uni qayta o'qib chiqsangiz, asosiy ma'lumotlarning, ehtimol, etishmayotganligi va eng katta qadriyat bo'lishi ehtimoldan xoli emas. Agar siz 1 dan 10 gacha bo'lgan raqamlarni qayta numaralandırma misoli to'g'ri bo'lsa, sizning reaktsiyangiz bu savolga javob berishi kerak, chunki u bunday talabning no maslahatini beradi (va ikkinchi yarim mening javobim aslida har qanday holatda bu imkoniyatni qoplaydi).
qo'shib qo'ydi muallif achrn, manba

Uch taklif:

  1. Yangilanishlarni har doim takrorlanishga olib kelmaydigan ketma-ketlikda qiling. Masalan, 2 va 3-ni almashtirish uchun avval null bilan 2-ni yangilang, keyin 3ni almashtirish uchun 2 ni qo'shing, so'ngra 3 ni kiriting.
  2. Ro'yxatga olingan ro'yxatning o'rtasida yozuvni kiritish uchun ehtimol so'rov kerak. Agar siz yozuvlaringizni ketma-ketlik bilan hisoblasangiz, unda bir nechta yozuvni qayta kiritishingiz kerak bo'ladi. Agar siz bog'langan ro'yxatdan foydalansangiz, faqat ikkitasini yangilashingiz kerak. Shuning uchun, men sizning bog'langan ro'yxatni ish vaqtida kamroq va kodni osonroq topishingiz mumkinligini kutishingizni kutaman.
  3. Sizning ustuningiz sort_key , ordinal yoki ehtimol joylashuvi nomi bilan tanishish odatiy deb o'ylayman.

Ruby'dagi Active Record uchun ochiq kodli dastur sizni ilhomlantirishi mumkin. act_as_list gem va bu fikrlarni solishtiring.

2
qo'shib qo'ydi
1. NULLni saqlashga ruxsat berish kerak. Lekin mening biznes mantiqim bunga yo'l qo'ymaydi va men buni xohlamayman
qo'shib qo'ydi muallif CarLaTeX, manba
OK. So'ngra boshqa javoblar siz uchun yaxshiroq ishlashi mumkin, masalan, s qo'g'irchoqli qiymat yoki vaqtincha qaydni oxirigacha yoki boshiga o'tkazish.
qo'shib qo'ydi muallif jroith, manba