Най-добри практики за меко изтриване (PHP/MySQL)

Проблем

В уеб приложение, занимаващо се с продукти и поръчки, искам да поддържам информация и връзки между бивши служители (потребители) и поръчките, които са обработвали. Искам да поддържам информация и връзки между остарели продукти и поръчки, които включват тези продукти.

Искам обаче служителите да могат да пречистват административните интерфейси, като премахване на бивши служители, остарели продукти, остарели продуктови групи и т.н.

Мисля да внедря soft-deletion. И така, как човек обикновено прави това?

Моите непосредствени мисли

Първата ми мисъл е да залепя колона "flag_softdeleted TINYINT NOT NULL DEFAULT 0" във всяка таблица с обекти, които трябва да могат да се изтриват меко. Или може би вместо това да използвате клеймо за време?

След това предоставям бутон „Показване на изтритите“ или „Възстановяване на изтриване“ във всеки съответен GUI. Щраквайки върху този бутон, ще включите меко изтритите записи в резултата. Всеки изтрит запис има бутон "Възстановяване". Това има ли смисъл?

Твоите мисли?

Освен това ще се радвам на всякакви връзки към подходящи ресурси.


person Community    schedule 16.02.2011    source източник
comment
В зависимост от размера на вашите таблици Служители/Продукти, може да е по-добре да създадете отделна таблица с идентификаторите на вашите Soft-Deleted елементи.   -  person drudge    schedule 16.02.2011
comment
клеймото за време винаги е полезно. въпреки това можете да използвате каквото искате - не е ТОЛКОВА голяма работа, за да задавате въпроси   -  person Your Common Sense    schedule 16.02.2011


Отговори (6)


Така го правя. Имам поле is_deleted, което по подразбиране е 0. Тогава заявките просто проверяват WHERE is_deleted = 0.

Опитвам се да стоя далеч от всякакви твърди изтривания, доколкото е възможно. Те са необходими понякога, но аз ги правя функция само за администратори. По този начин можем да изтрием трудно, но потребителите не могат...

Редактиране: Всъщност можете да използвате това, за да имате множество „слоеве“ за меко изтриване в приложението си. Така че всеки може да бъде код:

  • 0 -> Не е изтрито
  • 1 -> Soft Deleted, показва се в списъци с изтрити елементи за потребители за управление
  • 2 -> Софтуерно изтрито, не се показва за никой потребител, освен за администратори
  • 3 -> Показва се само за разработчици.

Наличието на другите 2 нива ще позволи на мениджърите и администраторите да изчистят изтритите списъци, ако станат твърде дълги. И тъй като кодът на интерфейса просто проверява за is_deleted = 0, той е прозрачен за интерфейса...

person ircmaxell    schedule 16.02.2011
comment
Ние правим многостепенна йерархия за нашата вътрешна CRM. Ние също използваме тригер за добавяне на изтрит запис към резервна таблица. Това е полезно, ако някой някога трябва да провери акаунт на ниво администратор или ако потребител на ниво администратор случайно изтрие грешен запис. - person Jestep; 17.02.2011
comment
ENUM вероятно ще бъде по-добър от 0,1,2,4. ENUM би бил самодокументиращ се и също толкова производителен. - person ; 17.02.2011
comment
Внимавайте да не бъдете победени с колона uniq: Вашите изтрити елементи все още ще съдържат стойност във вашата колона uniq, която може да не е това, което искате. Но можете да зададете тази колона на NULL, докато меко изтривате необработения файл, за да избегнете конфликти... - person Julien Palard; 22.05.2014
comment
какво ще стане, ако нормалният потребител софтуерно изтрие родителски запис, който има деца записи. В такъв случай родителският запис и всички негови деца ще бъдат скрити за нормалните потребители. Това е абсолютно същото като проблема с каскадното изтриване. Така че въпросът ми е как да проверя референтната цялост, преди меко да изтрия родителските записи? - person manas; 21.12.2016
comment
също така можете да използвате допълнително поле (или да замените това) като дата/час, за да знаете кога редът е бил изтрит - person JorgeGarza; 20.09.2017

Използването на меки изтривания е обичайно нещо за прилагане и те са изключително полезни за много неща, като:

  • Запазване на данни на потребител, когато той е изтрил нещо
  • Запазване на вашите собствени данни, когато изтриете нещо
  • Записвайте какво наистина се е случило (вид одит)
  • и така нататък

Има едно нещо, което искам да отбележа, че почти всички пропускат и то винаги се връща, за да ви ухапе в задната част. Потребителите на вашето приложение нямат същото разбиране за изтриване като вас.

Има различни степени на изтриване. Типичният потребител изтрива неща, когато (той) той

  • Направихте грешка и искате да премахнете лошите данни
  • Вече не иска да вижда нещо на екрана

Проблемът е, че ако не запишете намерението на изтриването, вашето приложение не може да направи разлика между грешни данни (които никога не е трябвало да бъдат създавани) и исторически правилни данни.

Разгледайте следните данни:

PRICES | item | price | deleted |
       +------+-------+---------+
       |   A  |  101  |    1    |
       |   B  |  110  |    1    |
       |   C  |  120  |    0    |
       +------+-------+---------+

Някои потребители не искат да показват цената на артикул B, тъй като вече не продават този артикул. Така че той го изтрива. Друг потребител създаде цена за артикул A по погрешка, така че го изтри и създаде цената за артикул C, както беше предвидено. Сега можете ли да ми покажете списък с цените на всички продукти? Не, защото или трябва да покажете потенциално грешни данни (A), или трябва да изключите всички цени освен текущите (C).

Разбира се, с горното може да се работи по различни начини. Мисълта ми е, че ВИЕ трябва да сте много наясно с това, което ВИЕ имате предвид под изтриване, и се уверете, че няма начин потребителите да го разберат погрешно. Един от начините би бил да принудите потребителя да направи избор (скриване/изтриване).

person Ronnis    schedule 16.02.2011

Ако имах съществуващ код, който удря тази таблица, щях да добавя колоната и да променя името на таблицата. След това бих създал изглед със същото име като текущата таблица, който избира само активните записи. По този начин никой от съществуващия код няма да се счупи и можете да имате колоната за меко изтриване. Ако искате да видите изтрития запис, избирате от базовата таблица, в противен случай използвате изгледа.

person HLGEM    schedule 16.02.2011
comment
Макар и кратко, вместо това бих приел това решение. Това по принцип се отнася за реални производствени бази данни и ОПРЕДЕЛЕНО е правилният начин. Никой не би искал да има изтрита колона и да е склонен просто да забрави да добави условието where deleted=0 в една от многото заявки, които ще се използват в приложението. - person MohamedEzz; 24.05.2014

Винаги съм използвал само изтрита колона, както споменахте. Наистина няма много повече от това. Вместо да изтриете записа, просто задайте полето deleted на true.

Някои компоненти, които създавам, позволяват на потребителя да преглежда всички изтрити записи и да ги възстановява, други просто показват всички записи, където изтрити = 0

person simshaun    schedule 16.02.2011

Вашата идея има смисъл и се използва често в производството, но за да я приложите, ще трябва да актуализирате доста код, за да отчетете новото поле. Друга възможност може да бъде архивиране (преместване) на "меко изтритите" записи в отделна таблица или база данни. Това също се прави често и превръща проблема в поддръжка, а не в (пре)програмиране. (Можете да накарате тригер на таблица да реагира на изтриването, за да архивира изтрития запис.)

Бих направил архивирането, за да избегна голяма актуализация на производствения код. Но ако искате да използвате полето за изтрит флаг, използвайте го като клеймо за време, за да ви даде допълнителна полезна информация отвъд булева стойност. (Null = не е изтрито.) Може също да искате да добавите поле DeletedBy, за да проследите потребителя, отговорен за изтриването на записа. Използването на две полета ви дава много информация, която ви казва кой какво е изтрил и кога. (Решението за две допълнителни полета също е нещо, което може да се направи в архивна таблица/база данни.)

person Paul Sasik    schedule 16.02.2011

Най-често срещаният сценарий, на който съм се натъквал, е това, което описвате, tinyint или дори bit, представляващо състояние IsActive или IsDeleted. В зависимост от това дали това се счита за „бизнес“ или „постоянство“ данни, те могат да бъдат записани в логиката на приложението/домейна възможно най-прозрачно, като например директно в съхранени процедури и да не са известни на кода на приложението. Но изглежда, че това е законна бизнес информация за вашите нужди, така че трябва да бъде известна в целия код. (Така че потребителите могат да преглеждат изтритите записи, както предлагате.)

Друг подход, който съм виждал, е да използвам комбинация от два времеви клейма, за да покажа "прозорец" на активност за даден запис. Това е малко повече код, за да го поддържате, но предимството е, че нещо може да бъде планирано да се самоизтрие меко в предварително определено време. Продуктите с ограничено време могат да бъдат зададени по този начин, когато бъдат създадени, например. (За да направите запис активен за неопределено време, може да използвате максимална стойност (или просто някаква абсурдно далечна бъдеща дата) или просто крайната дата да бъде null, ако сте съгласни с това.)

След това, разбира се, има допълнително разглеждане на неща, които се изтриват/възстановяват от време на време и проследяване на някакъв вид одит за това. Подходът с флаг знае само текущото състояние, подходът с времево клеймо знае само най-скорошния прозорец. Но всичко толкова сложно като одитна пътека определено трябва да се съхранява отделно от въпросните записи.

person David    schedule 16.02.2011
comment
Има ли BIT в MySQL?? Винаги съм използвал TINYINT. ума Каква е разликата между използването на BIT и TINYINT за булево поле? - person ; 16.02.2011
comment
@arex1337: bit всъщност е бил синоним на tinyint в MySQL: dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html Вероятно ви е по-добре с tinyint, но не ме цитирайте за това. В някои други бази данни една ключова разлика е, че bit не може да се индексира или обработва null по различен начин (или изобщо не) и т.н. Но аз нямам достатъчно преки познания за типовете данни, за да може MySQL наистина да бъде авторитет това. - person David; 16.02.2011