{"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\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","title":{"rendered":"Gesch\u00e4ftslogik in der Datenbank mit SchemaKeeper","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ziel dieses Artikels ist es, anhand der Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> Werkzeuge vorzustellen, die den Entwicklungsprozess von Datenbanken in PHP-Projekten, die PostgreSQL verwenden, erheblich erleichtern k\u00f6nnen.<\/p>\n<p><\/p>\n<p>Die Informationen in diesem Artikel sind vor allem f\u00fcr Entwickler n\u00fctzlich, die die M\u00f6glichkeiten von PostgreSQL maximal aussch\u00f6pfen m\u00f6chten, jedoch auf Herausforderungen bei der Pflege der in die Datenbank ausgelagerten Gesch\u00e4ftslogik sto\u00dfen. <\/p>\n<p><\/p>\n<p>Der Artikel wird die Vor- und Nachteile der Speicherung von Gesch\u00e4ftslogik in der Datenbank nicht beschreiben. Es wird davon ausgegangen, dass die Wahl bereits vom Leser getroffen wurde.<\/p>\n<p><\/p>\n<p>Folgende Fragen werden behandelt:<\/p>\n<p><\/p>\n<ol>\n<li>In welchem Format sollen Datenbank-Dumpstrukturen im Versionskontrollsystem (im Folgenden VCS) gespeichert werden?<\/li>\n<li>Wie lassen sich \u00c4nderungen in der Datenbankstruktur nach dem Speichern des Dumps verfolgen?<\/li>\n<li>Wie \u00fcbertr\u00e4gt man \u00c4nderungen in der Datenbankstruktur ohne Konflikte und gro\u00dfe Migrationsdateien auf andere Umgebungen?<\/li>\n<li>Wie kann der Prozess der parallelen Zusammenarbeit mehrerer Entwickler am Projekt organisiert werden?<\/li>\n<li>Wie k\u00f6nnen mehrere \u00c4nderungen in der Datenbankstruktur sicher in die Produktionsumgebung deployed werden?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<blockquote><p><strong>SchemaKeeper<\/strong> ist auf die Arbeit mit gespeicherten Prozeduren ausgelegt, die in der Sprache <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex>. Tests mit anderen Sprachen wurden nicht durchgef\u00fchrt, daher kann die Verwendung weniger effektiv oder sogar unm\u00f6glich sein.\n<\/p><\/blockquote>\n<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"v-kakom-vide-hranit-damp-struktury-bd-v-vcs\">In welcher Form sollten Sie den Dump der Datenbankstruktur in VCS speichern?<\/h2>\n<p><\/p>\n<p>Die Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> bietet die Funktion <code>saveDump<\/code>, die die Struktur aller Objekte aus der Datenbank in Form einzelner Textdateien speichert. Am Ende wird ein Verzeichnis erstellt, das die Datenbankstruktur enth\u00e4lt, unterteilt in gruppierte Dateien, die leicht in VCS hinzugef\u00fcgt werden k\u00f6nnen.<\/p>\n<p><\/p>\n<p>Betrachten wir die Umwandlung von Objekten aus der Datenbank in Dateien anhand mehrerer Beispiele:<\/p>\n<p><\/p>\n<p>Objekttyp<br \/>\nSchema<br \/>\nTitel<br \/>\nRelativer Pfad zur Datei<\/p>\n<p>Tabelle<br \/>\npublic<br \/>\naccounts<br \/>\n<code>.\/public\/tables\/accounts.txt<\/code><\/p>\n<p>Gespeicherte Prozedur<br \/>\npublic<br \/>\nauth(hash bigint)<br \/>\n<code>.\/public\/functions\/auth(int8).sql<\/code><\/p>\n<p>Darstellung<br \/>\nbooking<br \/>\ntariffs<br \/>\n<code>.\/booking\/views\/tariffs.txt<\/code><\/p>\n<p><\/p>\n<p>Der Inhalt der Dateien ist eine textuelle Darstellung der Struktur eines bestimmten Datenbankobjekts. Zum Beispiel wird der Inhalt f\u00fcr gespeicherte Prozeduren die vollst\u00e4ndige Definition der gespeicherten Prozedur enthalten, beginnend mit dem Block <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Wie aus der obigen Tabelle ersichtlich ist, enth\u00e4lt der Dateipfad Informationen \u00fcber den Typ, das Schema und den Namen des Objekts. Dieser Ansatz erleichtert die Navigation durch den Dump und die \u00dcberpr\u00fcfung von \u00c4nderungen in der Datenbank.<\/p>\n<p><\/p>\n<blockquote><p>Erweiterung <code>.sql<\/code> F\u00fcr Dateien mit dem Quellcode von Stored Procedures wurde ausgew\u00e4hlt, damit die IDE automatisch Werkzeuge f\u00fcr die Interaktion mit der Datenbank beim \u00d6ffnen der Datei bereitstellt.<\/p><\/blockquote>\n<p><\/p>\n<h2 id=\"kak-otslezhivat-izmeneniya-v-strukture-bd-posle-sohraneniya-dampa\">Wie lassen sich \u00c4nderungen in der Datenbankstruktur nach dem Speichern des Dumps verfolgen?<\/h2>\n<p><\/p>\n<p>Indem wir ein Dump der aktuellen Struktur der Datenbank in VCS speichern, erhalten wir die M\u00f6glichkeit, zu \u00fcberpr\u00fcfen, ob \u00c4nderungen an der Struktur der Datenbank nach der Erstellung des Dumps vorgenommen wurden. In der Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> gibt es eine Funktion zur Erkennung von \u00c4nderungen in der Struktur der Datenbank. <code>verifyDump<\/code>, die ohne Nebenwirkungen Informationen \u00fcber die Unterschiede zur\u00fcckgibt. <\/p>\n<p><\/p>\n<p>Eine alternative Methode zur \u00dcberpr\u00fcfung besteht darin, die Funktion erneut aufzurufen, <code>saveDump<\/code>, wobei dasselbe Verzeichnis angegeben wird, und im VCS nach \u00c4nderungen zu suchen. Da alle Objekte aus der Datenbank in separaten Dateien gespeichert sind, zeigt das VCS nur die ge\u00e4nderten Objekte an.<br \/>\nDer Hauptnachteil dieser Methode ist die Notwendigkeit, die Dateien zu \u00fcberschreiben, um \u00c4nderungen zu sehen.<\/p>\n<p><\/p>\n<h2 id=\"kak-perenosit-izmeneniya-v-strukture-bd-na-drugie-okruzheniya-bez-konfliktov-i-gigantskih-faylov-migraciy\">Wie \u00fcbertr\u00e4gt man \u00c4nderungen in der Datenbankstruktur ohne Konflikte und gro\u00dfe Migrationsdateien auf andere Umgebungen?<\/h2>\n<p><\/p>\n<p>Dank der Funktion <code>deployDump<\/code> Der Quellcode gespeicherter Prozeduren kann genau wie der normale Anwendungscode bearbeitet werden. Man kann neue Zeilen im Code gespeicherter Prozeduren hinzuf\u00fcgen oder entfernen und die \u00c4nderungen sofort ins Versionskontrollsystem \u00fcbermitteln oder gespeicherte Prozeduren durch das Erstellen oder L\u00f6schen der entsprechenden Dateien im Dump-Verzeichnis erstellen oder entfernen. <\/p>\n<p><\/p>\n<p>Um beispielsweise eine neue gespeicherte Prozedur im Schema zu erstellen, <code>public<\/code> gen\u00fcgt es, eine neue Datei mit der Endung <code>.sql<\/code> wird im Verzeichnis <code>public\/functions<\/code>zu erstellen, den Quellcode der gespeicherten Prozedur einschlie\u00dflich des Blocks <code>CREATE OR REPLACE FUNCTION<\/code>einzuf\u00fcgen, und dann die Funktion <code>deployDump<\/code>aufzurufen. Ebenso erfolgt die \u00c4nderung und L\u00f6schung der gespeicherten Prozedur. Auf diese Weise gelangt der Code gleichzeitig ins VCS und in die Datenbank. <\/p>\n<p><\/p>\n<p>Wenn im Quellcode einer gespeicherten Prozedur ein Fehler auftritt oder eine Unstimmigkeit zwischen dem Dateinamen und der gespeicherten Prozedur besteht, wird <code>deployDump<\/code> nicht ausgef\u00fchrt und zeigt eine Fehlermeldung an. Eine Disparit\u00e4t zwischen den gespeicherten Prozeduren im Dump und der aktuellen Datenbank ist bei Verwendung von <code>deployDump<\/code>.<\/p>\n<p><\/p>\n<blockquote><p>nicht m\u00f6glich. Bei der Erstellung einer neuen gespeicherten Prozedur ist es nicht notwendig, den richtigen Dateinamen manuell einzugeben. Es reicht aus, dass die Datei die Endung <code>.sql<\/code>. Nach dem Aufruf <code>deployDump<\/code> wird die Fehlermeldung den korrekten Namen enthalten, der zum Umbenennen der Datei verwendet werden kann.<\/p><\/blockquote>\n<p><code>deployDump<\/code> erm\u00f6glicht es, die Parameter der Funktion oder den R\u00fcckgabetyp ohne zus\u00e4tzliche Schritte zu \u00e4ndern, w\u00e4hrend man beim klassischen Ansatz zuerst<br \/>\ndie Funktion ausf\u00fchren musste <code>DROP FUNCTION<\/code>, und erst danach <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Leider gibt es einige Situationen, in denen <code>deployDump<\/code> \u00c4nderungen nicht automatisch angewendet werden k\u00f6nnen. Zum Beispiel, wenn eine Triggerfunktion gel\u00f6scht wird, die von mindestens einem Trigger verwendet wird. Solche Situationen m\u00fcssen manuell mit Migrationsdateien gel\u00f6st werden.<\/p>\n<p><\/p>\n<p>Wenn der Transfer von \u00c4nderungen in gespeicherten Prozeduren selbst <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex>, dann m\u00fcssen Migrationsdateien verwendet werden, um andere \u00c4nderungen in der Struktur zu \u00fcbertragen. Eine gute Bibliothek f\u00fcr die Arbeit mit Migrationen ist <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/doctrine\/migrations\">doctrine\/migrations<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Migrationen m\u00fcssen vor dem Ausf\u00fchren angewendet werden <code>deployDump<\/code>. Dadurch k\u00f6nnen alle \u00c4nderungen an der Struktur vorgenommen und problematische Situationen gel\u00f6st werden, sodass die \u00c4nderungen in den gespeicherten Prozeduren sp\u00e4ter problemlos \u00fcbertragen werden k\u00f6nnen.<\/p>\n<p><\/p>\n<p>Die Arbeit mit Migrationen wird in den folgenden Abschnitten ausf\u00fchrlicher beschrieben.<\/p>\n<p><\/p>\n<h2 id=\"kak-naladit-process-parallelnoy-raboty-nad-proektom-neskolkih-razrabotchikov\">Wie kann der Prozess der parallelen Zusammenarbeit mehrerer Entwickler am Projekt organisiert werden?<\/h2>\n<p><\/p>\n<p>Es ist notwendig, ein vollst\u00e4ndiges Initialisierungsskript f\u00fcr die Datenbank zu erstellen, das vom Entwickler auf seinem Arbeitsrechner ausgef\u00fchrt wird, um die Struktur der lokalen Datenbank mit dem im VCS gespeicherten Dump in Einklang zu bringen. Am einfachsten l\u00e4sst sich die Initialisierung der lokalen Datenbank in 3 Schritte unterteilen:<\/p>\n<p><\/p>\n<ol>\n<li>Import der Datei mit der Basisstruktur, die beispielsweise genannt werden k\u00f6nnte <code>base.sql<\/code> <\/li>\n<li>Anwendung von Migrationen<\/li>\n<li>Aufruf <code>deployDump<\/code><\/li>\n<\/ol>\n<p><\/p>\n<blockquote><p><code>base.sql<\/code> \u2014 das ist der Ausgangspunkt, \u00fcber den die Migrationen angewendet werden und wo <code>deployDump<\/code>, das hei\u00dft <code>base.sql + Migrationen + deployDump = aktuelle Datenbankstruktur<\/code>. Eine solche Datei kann mit dem Tool <code>pg_dump<\/code>generiert werden. Es wird <code>base.sql<\/code> ausschlie\u00dflich beim Initialisieren einer Datenbank von Grund auf verwendet.<\/p><\/blockquote>\n<p>Wir nennen das Skript zur vollst\u00e4ndigen Initialisierung der Datenbank <code>refresh.sh<\/code>. Der Arbeitsprozess k\u00f6nnte folgenderma\u00dfen aussehen:<\/p>\n<p><\/p>\n<ol>\n<li>Der Entwickler startet in seiner Umgebung <code>refresh.sh<\/code> und erh\u00e4lt die aktuelle Datenbankstruktur<\/li>\n<li>Der Entwickler beginnt mit der Arbeit an der zugewiesenen Aufgabe und passt die lokale Datenbank an die Bed\u00fcrfnisse der neuen Funktionalit\u00e4t an (<code>ALTER TABLE ... ADD COLUMN<\/code> usw.)<\/li>\n<li>Nach Abschluss der Aufgabe ruft der Entwickler die Funktion <code>saveDump<\/code>auf, um die in der Datenbank vorgenommenen \u00c4nderungen im VCS zu erfassen.<\/li>\n<li>Der Entwickler startet erneut <code>refresh.sh<\/code>, dann <code>verifyDump<\/code>, die jetzt eine Liste der \u00c4nderungen f\u00fcr die Migration anzeigt<\/li>\n<li>Der Entwickler \u00fcbertr\u00e4gt alle Struktur\u00e4nderungen in die Migrationsdatei und startet den Prozess erneut <code>refresh.sh<\/code> und <code>verifyDump<\/code>, und falls die Migration korrekt erstellt wurde, <code>verifyDump<\/code> wird es keine Unterschiede zwischen der lokalen DB und dem gespeicherten Dump zeigen<\/li>\n<\/ol>\n<p><\/p>\n<p>Der oben beschriebene Prozess ist mit den Prinzipien von Gitflow kompatibel. Jeder Branch im VCS enth\u00e4lt seine eigene Version des Dumps, und beim Zusammenf\u00fchren der Branches wird auch das Zusammenf\u00fchren der Dumps durchgef\u00fchrt. In den meisten F\u00e4llen sind nach dem Mergen keine weiteren Schritte erforderlich, aber wenn in verschiedenen Branches \u00c4nderungen vorgenommen wurden, zum Beispiel an derselben Tabelle, kann es zu Konflikten kommen.<\/p>\n<p><\/p>\n<p>Betrachten wir eine Konfliktsituation am Beispiel: Es gibt einen Branch <em>develop<\/em>, von dem zwei Branches abgezweigt wurden: <em>feature1<\/em> und <em>feature2<\/em>, die keine Konflikte mit <em>develop<\/em>haben, aber Konflikte untereinander aufweisen. Die Aufgabe besteht darin, beide Branches in <em>develop<\/em>zu mergen. F\u00fcr diesen Fall wird empfohlen, zun\u00e4chst einen der Branches in <em>develop<\/em>zu mergen und anschlie\u00dfend <em>develop<\/em> in den verbleibenden Branch, wobei die Konflikte im verbleibenden Branch gel\u00f6st werden, bevor der letzte Branch in <em>develop<\/em>. In der Phase der Konfliktl\u00f6sung kann es notwendig sein, die Migrationsdatei im letzten Branch anzupassen, damit sie mit dem endg\u00fcltigen Dump \u00fcbereinstimmt, der die Ergebnisse der Zusammenf\u00fchrungen enth\u00e4lt.<\/p>\n<p><\/p>\n<h2 id=\"kak-bezopasno-deploit-bolshee-kolichestvo-izmeneniy-v-strukture-bd-na-production-okruzhenie\">Wie k\u00f6nnen mehrere \u00c4nderungen in der Datenbankstruktur sicher in die Produktionsumgebung deployed werden?<\/h2>\n<p><\/p>\n<p>Dank des Dumps der aktuellen Datenbankstruktur im VCS besteht die M\u00f6glichkeit, die Produktionsdatenbank auf die genaue \u00dcbereinstimmung mit der geforderten Struktur zu \u00fcberpr\u00fcfen. Dies garantiert, dass alle \u00c4nderungen, die die Entwickler geplant hatten, erfolgreich in die Produktionsdatenbank \u00fcbertragen wurden.<\/p>\n<p><\/p>\n<p>Da <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl.html\">DDL<\/a><\/noindex> in PostgreSQL ist <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis\">transaktional<\/a><\/noindex>, es wird empfohlen, sich an die folgende Reihenfolge des Deployments zu halten, um im Falle eines unerwarteten Fehlers die \u00c4nderungen \"schmerzfrei\" durchzuf\u00fchren. <code>ROLLBACK<\/code>:<\/p>\n<p><\/p>\n<ol>\n<li>Eine Transaktion starten<\/li>\n<li>In der Transaktion alle Migrationen durchf\u00fchren<\/li>\n<li>In derselben Transaktion durchf\u00fchren <code>deployDump<\/code><\/li>\n<li>Ohne die Transaktion abzuschlie\u00dfen, durchf\u00fchren <code>verifyDump<\/code>. Wenn keine Fehler vorliegen, durchf\u00fchren <code>BEST\u00c4TIGEN<\/code>. Wenn Fehler vorliegen, durchf\u00fchren <code>ROLLBACK<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Diese Schritte lassen sich relativ einfach in bestehende Deploy-Ans\u00e4tze integrieren, einschlie\u00dflich Zero-Downtime.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Fazit<\/h1>\n<p><\/p>\n<p>Dank der oben beschriebenen Methoden l\u00e4sst sich die maximale Leistung aus Projekten mit \u201ePHP + PostgreSQL\u201c herausholen, wobei relativ wenig an Entwicklungskomfort geopfert werden muss im Vergleich zur Implementierung der gesamten Gesch\u00e4ftslogik im Hauptcode der Anwendung. Dar\u00fcber hinaus erscheint die Datenverarbeitung oft transparenter und erfordert weniger Code als dieselbe Funktionalit\u00e4t, die in PHP geschrieben ist. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex> Die Zielsetzung dieses Artikels ist es, am Beispiel der Bibliothek schema-keeper die Werkzeuge vorzustellen, die den Entwicklungsprozess von Datenbanken in PHP-Projekten mit PostgreSQL erheblich vereinfachen. Die Informationen in diesem Artikel sind vor allem f\u00fcr Entwickler n\u00fctzlich, die die M\u00f6glichkeiten von PostgreSQL optimal nutzen m\u00f6chten, aber mit den Herausforderungen umgehen m\u00fcssen, die mit der Auslagerung der Gesch\u00e4ftslogik in die Datenbank verbunden sind. Der Artikel wird nicht die Vorteile beschreiben.<\/p>\n<p>Quelle: <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 4.9.10 - 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 \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\" \/>\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\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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 \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\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/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\udd47Gesch\u00e4ftslogik in der Datenbank mit SchemaKeeper | ProHoster","description":"\ud83e\udd47Gesch\u00e4ftslogik in der Datenbank mit SchemaKeeper | ProHoster","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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 \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","og:url":"https:\/\/prohoster.info\/de\/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"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/31385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=31385"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/31385\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=31385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=31385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=31385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}