{"id":31385,"date":"2019-10-31T21:40:58","date_gmt":"2019-10-31T18:40:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\/"},"modified":"2019-10-31T21:40:58","modified_gmt":"2019-10-31T18:40:58","slug":"biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","status":"publish","type":"post","link":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","title":{"rendered":"Logica de afaceri \u00een baza de date folosind SchemaKeeper","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Scopul acestui articol este s\u0103 demonstreze prin exemplul unei biblioteci <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> instrumentele care faciliteaz\u0103 semnificativ procesul de dezvoltare a bazelor de date \u00een cadrul proiectelor PHP care utilizeaz\u0103 SGBD PostgreSQL.<\/p>\n<p><\/p>\n<p>Informa\u021biile din acest articol vor fi, \u00een primul r\u00e2nd, utile dezvoltatorilor care doresc s\u0103 valorifice la maximum posibilit\u0103\u021bile PostgreSQL, dar se confrunt\u0103 cu probleme de \u00eentre\u021binere a logicii de afaceri, externalizat\u0103 \u00een baza de date. <\/p>\n<p><\/p>\n<p>Articolul nu va descrie avantajele sau dezavantajele stoc\u0103rii logicii de afaceri \u00een baza de date. Se presupune c\u0103 alegerea a fost deja f\u0103cut\u0103 de cititor.<\/p>\n<p><\/p>\n<p>Vor fi discutate urm\u0103toarele subiecte:<\/p>\n<p><\/p>\n<ol>\n<li>\u00cen ce form\u0103 s\u0103 stoc\u0103m backup-ul structurii bazei de date \u00een sistemul de control al versiunilor (\u00een continuare VCS)<\/li>\n<li>Cum s\u0103 urm\u0103rim modific\u0103rile structurii bazei de date dup\u0103 salvarea backup-ului<\/li>\n<li>Cum s\u0103 transfer\u0103m modific\u0103rile structurii bazei de date \u00een alte medii f\u0103r\u0103 conflicte \u0219i fi\u0219iere de migrare uria\u0219e<\/li>\n<li>Cum s\u0103 organiz\u0103m procesul de lucru paralel la proiect de c\u0103tre mai mul\u021bi dezvoltatori<\/li>\n<li>Cum s\u0103 desf\u0103\u0219ur\u0103m \u00een siguran\u021b\u0103 un num\u0103r mai mare de modific\u0103ri \u00een structura bazei de date pe mediu de produc\u021bie<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<blockquote><p><strong>SchemaKeeper<\/strong> este utilizat pentru a lucra cu proceduri stocate scrise \u00een limbajul <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex>. Testarea cu alte limbaje nu a fost efectuat\u0103, prin urmare utilizarea poate fi nu at\u00e2t de eficient\u0103 sau imposibil\u0103.\n<\/p><\/blockquote>\n<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"v-kakom-vide-hranit-damp-struktury-bd-v-vcs\">\u00cen ce form\u0103 s\u0103 stoc\u0103m backup-ul structurii bazei de date \u00een VCS<\/h2>\n<p><\/p>\n<p>Biblioteca <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> ofer\u0103 func\u021bia <code>saveDump<\/code>, care salveaz\u0103 structura tuturor obiectelor din baza de date sub form\u0103 de fi\u0219iere text separate. La final, se creeaz\u0103 un director care con\u021bine structura bazei de date, \u00eemp\u0103r\u021bit\u0103 \u00een fi\u0219iere grupate, care pot fi ad\u0103ugate u\u0219or \u00een VCS.<\/p>\n<p><\/p>\n<p>S\u0103 analiz\u0103m transformarea obiectelor din baza de date \u00een fi\u0219iere prin c\u00e2teva exemple:<\/p>\n<p><\/p>\n<p>Tipul obiectului<br \/>\nSchema<br \/>\nDenumire<br \/>\nCalea relativ\u0103 c\u0103tre fi\u0219ier<\/p>\n<p>Tabel<br \/>\npublic<br \/>\naccounts<br \/>\n<code>.\/public\/tables\/accounts.txt<\/code><\/p>\n<p>Procedura stocat\u0103<br \/>\npublic<br \/>\nauth(hash bigint)<br \/>\n<code>.\/public\/functions\/auth(int8).sql<\/code><\/p>\n<p>Reprezentare<br \/>\nbooking<br \/>\ntariffs<br \/>\n<code>.\/booking\/views\/tariffs.txt<\/code><\/p>\n<p><\/p>\n<p>Con\u021binutul fi\u0219ierelor reprezint\u0103 o prezentare textual\u0103 a structurii unui obiect specific al bazei de date. De exemplu, pentru procedurile stocate, con\u021binutul fi\u0219ierului va fi defini\u021bia complet\u0103 a procedurii stocate, \u00eencep\u00e2nd cu blocul <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Dup\u0103 cum se vede din tabelul de mai sus, calea c\u0103tre fi\u0219ier con\u021bine informa\u021bii despre tipul, schema \u0219i numele obiectului. Aceast\u0103 abordare faciliteaz\u0103 navigarea \u0219i revizuirea modific\u0103rilor \u00een backup-ul bazei de date.<\/p>\n<p><\/p>\n<blockquote><p>Extensie <code>.sql<\/code> pentru fi\u0219ierele cu cod surs\u0103 al procedurilor stocate, a fost ales pentru ca IDE-urile s\u0103 ofere automat instrumente pentru interac\u021biunea cu baza de date la deschiderea fi\u0219ierului.<\/p><\/blockquote>\n<p><\/p>\n<h2 id=\"kak-otslezhivat-izmeneniya-v-strukture-bd-posle-sohraneniya-dampa\">Cum s\u0103 urm\u0103rim modific\u0103rile structurii bazei de date dup\u0103 salvarea backup-ului<\/h2>\n<p><\/p>\n<p>Prin salvarea unui dump al structurii curente a bazei de date \u00een VCS, ob\u021binem posibilitatea de a verifica dac\u0103 s-au efectuat modific\u0103ri \u00een structur\u0103 dup\u0103 crearea dump-ului. \u00cen bibliotec\u0103 <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> pentru identificarea modific\u0103rilor structurii bazei de date este prev\u0103zut\u0103 func\u021bia <code>verifyDump<\/code>, care returneaz\u0103 informa\u021bii despre diferen\u021be f\u0103r\u0103 efecte secundare. <\/p>\n<p><\/p>\n<p>O metod\u0103 alternativ\u0103 de verificare este de a apela din nou func\u021bia <code>saveDump<\/code>, specific\u00e2nd aceea\u0219i direc\u021bie, \u0219i a verifica \u00een VCS existen\u021ba modific\u0103rilor. Deoarece toate obiectele din baza de date sunt salvate \u00een fi\u0219iere separate, VCS va ar\u0103ta doar obiectele care s-au modificat.<br \/>\nPrincipalul dezavantaj al acestei metode este necesitatea de a rescrie fi\u0219ierele pentru a vedea modific\u0103rile.<\/p>\n<p><\/p>\n<h2 id=\"kak-perenosit-izmeneniya-v-strukture-bd-na-drugie-okruzheniya-bez-konfliktov-i-gigantskih-faylov-migraciy\">Cum s\u0103 transfer\u0103m modific\u0103rile structurii bazei de date \u00een alte medii f\u0103r\u0103 conflicte \u0219i fi\u0219iere de migrare uria\u0219e<\/h2>\n<p><\/p>\n<p>Thanks to the function <code>deployDump<\/code> codul surs\u0103 al procedurilor stocate poate fi modificat exact ca un cod surs\u0103 obi\u0219nuit al aplica\u021biei. Po\u021bi ad\u0103uga\/\u0219terge noi linii \u00een codul procedurilor stocate \u0219i trimite imediat modific\u0103rile \u00een sistemul de control al versiunilor, sau crea\/\u0219terge proceduri stocate prin crearea\/\u0219tergerea fi\u0219ierelor corespunz\u0103toare \u00een directorul cu dump-ul. <\/p>\n<p><\/p>\n<p>De exemplu, pentru a crea o nou\u0103 procedur\u0103 stocat\u0103 \u00een schema <code>public<\/code> este suficient s\u0103 creezi un fi\u0219ier nou cu extensia <code>.sql<\/code> \u00een directorul <code>public\/functions<\/code>, s\u0103 plasezi \u00een el codul surs\u0103 al procedurii stocate, inclusiv blocul <code>CREATE OR REPLACE FUNCTION<\/code>, apoi s\u0103 apelezi func\u021bia <code>deployDump<\/code>. La fel se procedeaz\u0103 \u0219i \u00een cazul modific\u0103rii sau \u0219tergerii unei proceduri stocate. Astfel, codul ajunge simultan at\u00e2t \u00een VCS, c\u00e2t \u0219i \u00een baza de date. <\/p>\n<p><\/p>\n<p>Dac\u0103 \u00een codul surs\u0103 al oric\u0103rei proceduri stocate apare o eroare sau o neconcordan\u021b\u0103 \u00eentre numele fi\u0219ierului \u0219i procedura stocat\u0103, atunci <code>deployDump<\/code> nu va fi executat\u0103, afi\u0219\u00e2nd mesajul de eroare. Neconcordan\u021ba dintre procedurile stocate \u00eentre dump \u0219i baza de date curent\u0103 este imposibil\u0103 folosind <code>deployDump<\/code>.<\/p>\n<p><\/p>\n<blockquote><p>Atunci c\u00e2nd se creeaz\u0103 o nou\u0103 procedur\u0103 stocat\u0103, nu este necesar s\u0103 introduci manual numele corect al fi\u0219ierului. Este suficient ca fi\u0219ierul s\u0103 aib\u0103 extensia <code>.sql<\/code>. Dup\u0103 apelarea lui, <code>deployDump<\/code> mesajul de eroare va con\u021bine numele corect, care poate fi folosit pentru a redenumi fi\u0219ierul.<\/p><\/blockquote>\n<p><code>deployDump<\/code> permete modificarea parametrilor func\u021biei sau tipului de returnare f\u0103r\u0103 ac\u021biuni suplimentare, \u00een timp ce \u00een abordarea clasic\u0103 ar fi fost necesar s\u0103<br \/>\nmai \u00eent\u00e2i s\u0103 execu\u021bi <code>DROP FUNCTION<\/code>, \u0219i abia apoi <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Din p\u0103cate, exist\u0103 anumite situa\u021bii \u00een care <code>deployDump<\/code> nu se pot aplica automat modific\u0103rile. De exemplu, dac\u0103 se \u0219terge o func\u021bie declan\u0219atoare, care este utilizat\u0103 de un declan\u0219ator. Astfel de situa\u021bii se rezolv\u0103 manual cu ajutorul fi\u0219ierelor de migrare.<\/p>\n<p><\/p>\n<p>Dac\u0103 transferul modific\u0103rilor \u00een procedurile stocate este responsabilitatea \u00eens\u0103\u0219i <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex>, atunci pentru transferul celorlalte modific\u0103ri \u00een structur\u0103 este necesar s\u0103 se utilizeze fi\u0219iere de migrare. De exemplu, o bibliotec\u0103 bun\u0103 pentru lucrul cu migrarea este <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/doctrine\/migrations\">doctrine\/migrations<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Migra\u021biile trebuie s\u0103 fie aplicate \u00eenainte de lansare <code>deployDump<\/code>. Acest lucru permite efectuarea tuturor modific\u0103rilor \u00een structur\u0103 \u0219i rezolvarea problemelor, astfel \u00eenc\u00e2t modific\u0103rile din procedurile stocate s\u0103 fie transferate ulterior f\u0103r\u0103 probleme.<\/p>\n<p><\/p>\n<p>Mai multe detalii despre lucrul cu migra\u021biile vor fi prezentate \u00een sec\u021biunile urm\u0103toare.<\/p>\n<p><\/p>\n<h2 id=\"kak-naladit-process-parallelnoy-raboty-nad-proektom-neskolkih-razrabotchikov\">Cum s\u0103 organiz\u0103m procesul de lucru paralel la proiect de c\u0103tre mai mul\u021bi dezvoltatori<\/h2>\n<p><\/p>\n<p>Este necesar s\u0103 se creeze un script de ini\u021bializare complet\u0103 a Bazei de Date, care va fi rulat de dezvoltator pe ma\u0219ina sa de lucru, aduc\u00e2nd structura bazei de date locale \u00een conformitate cu dump-ul salvat \u00een VCS. Cel mai simplu este s\u0103 se \u00eempart\u0103 ini\u021bializarea bazei de date locale \u00een 3 pa\u0219i:<\/p>\n<p><\/p>\n<ol>\n<li>Importarea unui fi\u0219ier cu structura de baz\u0103, care se va numi, de exemplu, <code>base.sql<\/code> <\/li>\n<li>Aplicarea migra\u021biilor<\/li>\n<li>Apel <code>deployDump<\/code><\/li>\n<\/ol>\n<p><\/p>\n<blockquote><p><code>base.sql<\/code> \u2014 aceasta este punctul de plecare, pe care se aplic\u0103 migra\u021biile \u0219i se execut\u0103 <code>deployDump<\/code>, adic\u0103 <code>base.sql + migra\u021bii + deployDump = structura actualizat\u0103 a bazei de date<\/code>. Un astfel de fi\u0219ier poate fi generat cu ajutorul utilitarului <code>pg_dump<\/code>. Este utilizat <code>base.sql<\/code> exclusiv pentru ini\u021bializarea bazei de date de la zero.<\/p><\/blockquote>\n<p>S\u0103 numim scriptul de ini\u021bializare complet\u0103 a bazei de date <code>refresh.sh<\/code>. Fluxul de lucru poate ar\u0103ta \u00een felul urm\u0103tor:<\/p>\n<p><\/p>\n<ol>\n<li>Dezvoltatorul ruleaz\u0103 \u00een mediul s\u0103u <code>refresh.sh<\/code> \u0219i ob\u021bine structura actualizat\u0103 a bazei de date<\/li>\n<li>Dezvoltatorul \u00eencepe lucrul la sarcina primit\u0103, modific\u00e2nd baza de date local\u0103 conform nevoilor func\u021bionalit\u0103\u021bii noi (<code>ALTER TABLE ... ADD COLUMN<\/code> etc.)<\/li>\n<li>Dup\u0103 finalizarea sarcinii, dezvoltatorul apeleaz\u0103 func\u021bia <code>saveDump<\/code>, pentru a \u00eenregistra \u00een VCS modific\u0103rile efectuate \u00een baza de date<\/li>\n<li>Dezvoltatorul ruleaz\u0103 din nou <code>refresh.sh<\/code>, apoi <code>verifyDump<\/code>, care acum arat\u0103 lista modific\u0103rilor pentru includerea \u00een migra\u021bie<\/li>\n<li>Dezvoltatorul transfer\u0103 toate modific\u0103rile structurii \u00een fi\u0219ierul de migrare, \u00eel ruleaz\u0103 din nou <code>refresh.sh<\/code> \u0219i <code>verifyDump<\/code>, \u0219i, dac\u0103 migrarea este corect formulat\u0103, <code>verifyDump<\/code> va ar\u0103ta absen\u021ba diferen\u021belor \u00eentre baza de date local\u0103 \u0219i dump-ul salvat.<\/li>\n<\/ol>\n<p><\/p>\n<p>Procesul descris mai sus este compatibil cu principiile gitflow. Fiecare ramur\u0103 din VCS va con\u021bine propria versiune a dump-ului, iar la \u00eembinarea ramurilor se va face \u00eembinarea dump-urilor. \u00cen majoritatea cazurilor, dup\u0103 \u00eembinare nu este necesar s\u0103 se efectueze ac\u021biuni suplimentare, dar dac\u0103 modific\u0103ri au fost f\u0103cute \u00een ramuri diferite, de exemplu, \u00een aceea\u0219i tabel\u0103, pot ap\u0103rea conflicte.<\/p>\n<p><\/p>\n<p>S\u0103 lu\u0103m \u00een considerare o situa\u021bie conflictual\u0103 pe exemplul: exist\u0103 o ramur\u0103 <em>develop<\/em>, de la care s-au bifurcat dou\u0103 ramuri: <em>feature1<\/em> \u0219i <em>feature2<\/em>, care nu au conflicte cu <em>develop<\/em>, dar au conflicte \u00eentre ele. Obiectivul este de a \u00eembina ambele ramuri \u00een <em>develop<\/em>. Pentru astfel de cazuri, se recomand\u0103 mai \u00eent\u00e2i \u00eembinarea uneia dintre ramuri \u00een <em>develop<\/em>, iar apoi \u00eembinarea <em>develop<\/em> \u00een ramura r\u0103mas\u0103, rezolv\u00e2nd \u00een acela\u0219i timp conflictele \u00een ramura r\u0103mas\u0103, dup\u0103 care se va efectua \u00eembinarea ultimei ramuri \u00een <em>develop<\/em>. \u00cen etapa de rezolvare a conflictelor poate fi necesar s\u0103 se corecteze fi\u0219ierul de migrare din ultima ramur\u0103, astfel \u00eenc\u00e2t acesta s\u0103 corespund\u0103 dump-ului final, care include rezultatele \u00eembin\u0103rilor.<\/p>\n<p><\/p>\n<h2 id=\"kak-bezopasno-deploit-bolshee-kolichestvo-izmeneniy-v-strukture-bd-na-production-okruzhenie\">Cum s\u0103 desf\u0103\u0219ur\u0103m \u00een siguran\u021b\u0103 un num\u0103r mai mare de modific\u0103ri \u00een structura bazei de date pe mediu de produc\u021bie<\/h2>\n<p><\/p>\n<p>Datorit\u0103 existen\u021bei \u00een VCS a dump-ului structurii actuale a bazei de date, apare posibilitatea de a verifica baza de date de produc\u021bie pentru a avea o coresponden\u021b\u0103 exact\u0103 cu structura necesar\u0103. Acest lucru garanteaz\u0103 c\u0103 toate modific\u0103rile pe care le-au inten\u021bionat dezvoltatorii s-au transferat cu succes \u00een baza de date de produc\u021bie.<\/p>\n<p><\/p>\n<p>Deoarece <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl.html\">DDL<\/a><\/noindex> \u00een PostgreSQL este <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis\">tranzac\u021bional<\/a><\/noindex>, se recomand\u0103 respectarea urm\u0103toarei ordini de desf\u0103\u0219urare, pentru a putea, \u00een caz de eroare neprev\u0103zut\u0103, s\u0103 efectuezi \u201ef\u0103r\u0103 durere\u201d <code>ROLLBACK<\/code>:<\/p>\n<p><\/p>\n<ol>\n<li>\u00cencepe tranzac\u021bia<\/li>\n<li>\u00cen tranzac\u021bie, efectueaz\u0103 toate migra\u021biile<\/li>\n<li>\u00cen aceea\u0219i tranzac\u021bie, efectueaz\u0103 <code>deployDump<\/code><\/li>\n<li>F\u0103r\u0103 a \u00eenchide tranzac\u021bia, efectueaz\u0103 <code>verifyDump<\/code>. Dac\u0103 nu sunt erori, efectueaz\u0103 <code>COMMIT<\/code>. Dac\u0103 sunt erori, efectueaz\u0103 <code>ROLLBACK<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Ace\u0219ti pa\u0219i sunt destul de u\u0219or de integrat \u00een abord\u0103rile existente de desf\u0103\u0219urare a aplica\u021biilor, inclusiv zero-downtime.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Concluzie<\/h1>\n<p><\/p>\n<p>Datorit\u0103 metodelor descrise mai sus, se poate extrage maximul de performan\u021b\u0103 din proiectele \u201ePHP + PostgreSQL\u201d, sacrific\u00e2nd astfel o cantitate relativ mic\u0103 de confort \u00een dezvoltare \u00een compara\u021bie cu implementarea \u00eentregii logici de afaceri \u00een codul principal al aplica\u021biei. Mai mult, procesarea datelor \u00een <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex> aparent, este mai transparent\u0103 \u0219i necesit\u0103 mai pu\u021bin cod dec\u00e2t aceea\u0219i func\u021bionalitate scris\u0103 \u00een PHP.<\/p>\n<p>Sursa: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/447746\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 PHP-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0445 \u0421\u0423\u0411\u0414 PostgreSQL. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 \u0445\u043e\u0442\u044f\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 PostgreSQL, \u043d\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043d\u043e\u0439 \u0432 \u0411\u0414. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-31385","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Logica de afaceri \u00een baza de date cu ajutorul SchemaKeeper | ProHoster","description":"Scopul acestui articol este de a ar\u0103ta, prin exemplul bibliotecii schema-keeper, uneltele care permit o \u00eembun\u0103t\u0103\u021bire semnificativ\u0103.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster","og:description":"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.","og:url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:40:58+00:00","article:modified_time":"2019-10-31T18:40:58+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31385","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 05:54:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:17:26","updated":"2026-01-21 05:54:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/31385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=31385"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/31385\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=31385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=31385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=31385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}