AUTO_INCREMENT müsste 2x gebraucht werden
Andy Nail
- mysql
0 TS0 pl0 dedlfix0 pl0 Christian Kruse
0 Regina Schaukrug
Hallo zusammen,
auf meiner Seite brauche ich einmal ein Feld das automatisch weiterzählt wenn ein neuer Eintrag hinzugefügt wird mit dem Namen ID. Doch brauche ich noch ein weiteres Feld das weiterzählt und die Position auf der Seite bestimmt. Es sollte also automatisch weiterzählen, aber auch zu ändern möglich sein. Und ein weiterzählendes Feld erhalte ich ja mit einem AUTO_INCREMENT Feld, doch erhalte ich eine Fehlermeldung keine 2 Felder anlegen zu können!
Also wie schaffe ich das jetzt? Und möchte mich bereits jetzt für jede Hilfe und jede Mühe bedanken!
Also Danke und hoffe mit Erfolg mit Gruß Andreas
Hello,
zeig mal bitte das Create-Statement.
Was soll passieren, wenn es die Position schon belegt ist?
Hast Du schon eine Prozedur für das Erstellen einer Lücke, also das Verschieben von Positionsnummern?
Sollen Lücken auch wieder gechlossen werden können, oder ist das dann egal?
Liebe Grüße
Tom S.
Jo Hallo Du,
sollte die Tabelle nicht in einem AUTO_INCREMENT Feld automatisch weiterzählen wenn per sql ein neuer Eintrag angelegt wird? Und So füge ich die Einträge hinzu und frage sie auch per sql ab. D. h. also, dass ich mit sql sort by Position abfragen will, sodass es doch egal sein sollte wenn da eine Lücke drin sein sollte? Ich bräuchte einfach einen neuen Wert der den Eintrag erst einmal an das Ende stellt!
OK? Also auf jeden Fall schonmal Danke mit Gruß Andreas
Hello,
sollte die Tabelle nicht in einem AUTO_INCREMENT Feld automatisch weiterzählen wenn per sql ein neuer Eintrag angelegt wird?
Autoincrement wird automatisch hochgezählt bis zum maxbigint. Wenn Du aber in die automatische Numerierung eingreifst, was bei MySQL geht, ist die Reihenfolge nicht mehr garantiert.
Und So füge ich die Einträge hinzu und frage sie auch per sql ab. D. h. also, dass ich mit sql sort by Position abfragen will, sodass es doch egal sein sollte wenn da eine Lücke drin sein sollte? Ich bräuchte einfach einen neuen Wert der den Eintrag erst einmal an das Ende stellt!
Du kannst nur eine Autoincrement-Spalte in jeder Tabelle haben.
OK? Also auf jeden Fall schonmal Danke mit Gruß Andreas
Du kannst selbstverständlich in einer zweiten Spalte selber entscheiden, wie dort die Werte sind. Es wird ja vermutlich ein unique Kombinationsschlüssel aus (Seitennummer und Position) werden müssen.
Wenn Du also eine Liste hast
--id---seite---pos---itemtype---attribs------------------------------
10 1 1 a a10, http://example.com, ,example.com
11 1 2 div d2, viel text
13 2 1 h1 h1-1, Zweite Seite
und willst dann auf der ersten Seite ein Item anhängen, dann kennst Du doch die Seitennummer und die Positon schon. Und wenn zwischen Abfrage (Erstellen der Liste) und Einfügeaktion jemand anders schneller war, dann weigert sich die Tabelle, weil Du den Kombinationsschlüssel unique anlegst.
Du brauchst aber jetzt eine Funktion, um Lücken zu schaffen, also um z. B. alle Positionsnummern in der Seite 1, die größer sind als 1, um eeins hochzuzählen. Anschließend kannst Du die entstandene Lücke dann belegen.
Verstanden?
Mehr gerne auf konkrete Rückfrage.
Liebe Grüße
Tom S.
Hallo
OK, dann sollte ich mich mit einer Funktion zur Lückenschließung beschäftigen. Doch wöllte ich erst einmal, dass der Wert weitergezählt wird. Ich verwende server2go. bekomme ein Formular zur Erstellung der Felderund will so ein zweites AUTO_INCREMENT Feld anlegen und erhalte dann die Fehlermeldung. Ist es also nicht unbedingt unmöglich ein zweites AUTO_INCREMENT Feld anlegen zu können, so dass sich dieses Problem also nur auf server2go bezieht?
Danke Gruß Andreas
Hello,
OK, dann sollte ich mich mit einer Funktion zur Lückenschließung beschäftigen.
Lücken schaffen war das Thema.
Ist es also nicht unbedingt unmöglich ein zweites AUTO_INCREMENT Feld anlegen zu können, so dass sich dieses Problem also nur auf server2go bezieht?
Das Problem bezieht sich auf alle Datenbanken, die ich kenne. Keine lässt mehr als eine Autoincrementspalte pro Tabelle zu.
Vielleicht kannst Du einen Trigger und/oder eine Subquery nutzen dafür.
Liebe Grüße
Tom S.
Hello,
Vielleicht kannst Du einen Trigger und/oder eine Subquery nutzen dafür.
Für das Insert funktioniert es so, ob es zulässig ist, weiß ich nicht:
CREATE TABLE `items` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`page` INT(11) NOT NULL DEFAULT '0',
`pos` INT(11) NULL DEFAULT '0',
`itemtype` CHAR(50) NOT NULL DEFAULT '0',
`attribs` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE INDEX `page_pos` (`page`, `pos`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=1
;
CREATE DEFINER=`root`@`localhost` TRIGGER `items_before_insert` BEFORE INSERT ON `items` FOR EACH ROW BEGIN
set @spos = (select max(pos) from items where page = new.page);
if (isnull(@spos)) then
set new.pos = 1;
else
set new.pos = @spos + 1;
end if;
END
Was man beim Update alles noch bedenken müsste, sollst Du mal selber überlegen.
Und wenn Du dann beim Update auf die Finger geklopft bekommst vom DBMS, weil die Positionsnummer schon belegt war, dann musst Du eben vorhher eine Lücke schaffen und dann erst das Update durchführen.
Liebe Grüße
Tom S.
Hello,
Und bevor ich es wieder wegdrücke ...
Hier die Lücke nach pos 1 auf page 3
update items
set pos = pos+1
where page = 3 and pos > 1
order by page, pos desc;
Kannst Du in eine Datenbankprozedur einbauen, die erst prüft, ob der Satz eingefügt werden kann und wenn das nicht klappt, die Lücke schafft und dann das Einfügen nochmal versucht.
Liebe Grüße
Tom S.
Hallo TS,
Das Problem bezieht sich auf alle Datenbanken, die ich kenne. Keine lässt mehr als eine Autoincrementspalte pro Tabelle zu.
Dann kennst du nur MySQL? MSSQL, Oracle, DB2, PostgreSQL – sie alle erlauben es, beliebig viele Sequences zu definieren. Man kann sogar die gleiche Sequence verwenden, um mehrere Spalten zu befüllen.
Zur Erklärung: AUTO_INCREMENT
ist eine kaputte Variante von Sequences. Der Standard sieht vor, dass man eine Sequence erstellt und den default value einer Spalte auf nextval('sequence_name')
setzt.
In MySQL kann man das übrigens mit Triggern nachbauen, aber von Haus aus wird das in der Tat nicht unterstützt.
LG,
CK
Hello,
Zur Erklärung:
AUTO_INCREMENT
ist eine kaputte Variante von Sequences. Der Standard sieht vor, dass man eine Sequence erstellt und den default value einer Spalte aufnextval('sequence_name')
setzt.
Und das geht dann auch gruppiert und automatisch?
In MySQL kann man das übrigens mit Triggern nachbauen, aber von Haus aus wird das in der Tat nicht unterstützt.
Das haben wir hier getan für pos
, und zwar gruppiert nach page
.
Liebe Grüße
Tom S.
Hallo TS,
Zur Erklärung:
AUTO_INCREMENT
ist eine kaputte Variante von Sequences. Der Standard sieht vor, dass man eine Sequence erstellt und den default value einer Spalte aufnextval('sequence_name')
setzt.Und das geht dann auch gruppiert und automatisch?
Das ist es nicht, worauf ich mich bezogen habe. Ich bezog mich auf das, was ich als Zitat stehen ließ:
Das Problem bezieht sich auf alle Datenbanken, die ich kenne. Keine lässt mehr als eine Autoincrementspalte pro Tabelle zu.
Hervorhebung von mir.
Ich denke aber, dass dir das auch klar ist.
LG,
CK
Hello,
Oh, entschuldige bitte.
Ich hatte es auf das Anliegen des OP bezogen, dass das auch automatisch mit Sequences zu erledigen wäre.
Liebe Grüße
Tom S.
Hallo TS,
Ich hatte es auf das Anliegen des OP bezogen, dass das auch automatisch mit Sequences zu erledigen wäre.
Nein, das Problem hast du mit der Trigger-Lösung ja bereits ausreichend behandelt.
LG,
CK
Tach!
Zur Erklärung:
AUTO_INCREMENT
ist eine kaputte Variante von Sequences.
Ich würde es als eine für die überwiegende Mehrheit der Fälle ausreichende und deutliche Vereinfachung gegenüber dem Erstellen und Anwenden von Sequenzen bezeichnen.
dedlfix.
Hallo dedlfix,
Zur Erklärung:
AUTO_INCREMENT
ist eine kaputte Variante von Sequences.Ich würde es als eine für die überwiegende Mehrheit der Fälle ausreichende und deutliche Vereinfachung gegenüber dem Erstellen und Anwenden von Sequenzen bezeichnen.
Warum denkst du das? Warum sollte pk int autoincrement primary key
einfacher sein als pk serial primary key
?
LG,
CK
Tach!
Zur Erklärung:
AUTO_INCREMENT
ist eine kaputte Variante von Sequences.Ich würde es als eine für die überwiegende Mehrheit der Fälle ausreichende und deutliche Vereinfachung gegenüber dem Erstellen und Anwenden von Sequenzen bezeichnen.
Warum denkst du das? Warum sollte
pk int autoincrement primary key
einfacher sein alspk serial primary key
?
Hmm, ich kenne das nur von einer Oracle-Version vor einigen Jahren. Da musste man die Sequenz anlegen und jeweils per Namen ansprechen, um den Wert ins Feld zu bekommen.
dedlfix.
Hello,
Warum denkst du das? Warum sollte
pk int autoincrement primary key
einfacher sein alspk serial primary key
?Hmm, ich kenne das nur von einer Oracle-Version vor einigen Jahren. Da musste man die Sequenz anlegen und jeweils per Namen ansprechen, um den Wert ins Feld zu bekommen.
Bei Informix ist das auch so. Man muss die Sequence als Create-berechtigter User anlegen, und kann sie dann als berechtigter Usage-User benutzen in seiner DML-Definition.
Da das aber alles ziemlich stumpf abläuft, habe ich überhaupt nicht daran gedacht, das hier für den OP in Betracht zu ziehen. Und mit Informix komme ich noch ca. alle 6-8 Monate effektiv in Berührung, so dass Christian schon Recht hat. Ich kenne das nicht mehr wirklich.
BTW: Ich kenne wirklich nur MySQL und einige Desktopdatenbanken, usw., die AUTOINCREMENT (aka AUTOKEY, AUTOINDEX) benutzen, und die lassen davon alle nur eine Spalte pro Tabelle zu. Sequences sind mMn ein ganz anderes Kaliber. Und sie wären keine Lösung für die Aufgabe des OP!
Liebe Grüße
Tom S.
Tag.
Ich bräuchte einfach einen neuen Wert der den Eintrag erst einmal an das Ende stellt!
Du kannst die Sortierungsspalte frei lassen, solange du für den jeweiligen Eintrag keine gesonderte Sortierung wünschst. Im select sortierst du dann je nachdem, ob die Sortierungsspalte gesetzt ist, nach dieser Spalte oder nach der autoincrement-Spalte:
select id,sortierung from bla order by ifnull(sortierung, id), id;
+----+------------+
| id | sortierung | ifnull(sortierung, id), sortierung
+----+------------+
| 4 | 1 | 1
| 2 | NULL | 2
| 1 | 3 | 3
| 3 | NULL | 4
+----+------------+
(Die zusätzliche Sortierung nach der autoincrement-Spalte id hilft bei doppelten Einträgen in sortierung. Das könnte einfacher sein als in der Sortierungsspalte für einzigartige Werte zu sorgen.)
Beim manuellen Bearbeiten der Liste übernimmst du einfach den autoincrement-Wert der neuen Nachbarspalte in die Sortierungsspalte.
Schönen Abend
Doch brauche ich noch ein weiteres Feld das weiterzählt
Bei welchem Ereignis bzw. aus welchem Anlass soll da weitergezählt werden? Abgesehen davon kannst Du fortlaufnde Nummern auch außerhalb von MySQL erzeugen. pl
Tach!
Abgesehen davon kannst Du fortlaufnde Nummern auch außerhalb von MySQL erzeugen.
Kann man. Ist nur nicht ganz so schön, weil man dazu immer diesen Platz außerhalb beachten muss, wenn man Änderungen vornehmen möchte. Ein Trigger ist da schon komfortabler, den kann man nicht vergessen auszuführen.
dedlfix.
Ich denke auch, dass das Problem mit einem Trigger besser gelöst werden kann. MfG
Hallo dedlfix,
Abgesehen davon kannst Du fortlaufnde Nummern auch außerhalb von MySQL erzeugen.
Kann man. Ist nur nicht ganz so schön, weil man dazu immer diesen Platz außerhalb beachten muss, wenn man Änderungen vornehmen möchte.
Ein größeres Problem sehe ich hier in Concurrency. Man muss, falls man das tatsächlich außerhalb macht, auf jeden Fall die Zeile exklusiv sperren (SELECT … FOR UPDATE
), damit man nicht doppelte Werte erzeugt.
Ein Trigger ist da schon komfortabler, den kann man nicht vergessen auszuführen.
Komfortabler und weniger anfällig für Fehler.
LG,
CK
Einführendes Gemecker: Das junge Volk lernt schlaues Zeug wie MVC aber nicht mehr die echten Basics. Einführende Erläuterung: Zu den "echten Basics" zählt die strikte Trennung zwischen Daten, Programm und Darstellung. Berechenbare Darstellungsoptionen, die sich womöglich sogar von Benutzer zu Benutzer oder Sitzung zu Sitzung (Bildschirmgröße -> Anzahl der Resultate je Seite) ändern können, haben definitiv nichts in der Datenbank zu suchen. Das betrifft hier also die Seitennummer und die Seitenposition.
Vorab: Es gibt auch keinen haltbaren Grund auf das "3. Resultat der 5. Seite" zugreifen zu wollen. Wenn man sich einen bestimmten (bekannten) Datensatz aus der Menge herausklauben will, dann benutzt man dessen ID.
Doch brauche ich noch ein weiteres Feld das weiterzählt und die Position auf der Seite bestimmt.
Nein. Braucht Du nicht.
Vorliegend können die sich ändern und man die nämlich leicht und sehr schnell bei der Ausgabe berechnen. Ich formuliere es mal in PHP:
$AnzahlPerSeite = 10; #variablel, config, userdefined ...
$counter = 0; #Zähler der aus der Datenbank wieder gegebenen Werte, ID wird nicht benutzt, da
#Autoincrement (Lücken!)
foreach (…) {# wie auch immer Du die Daten aus dem Resultset holst
$SeitenNr = floor( $counter / $AnzahlPerSeite );
$SeitenPos = $counter % $AnzahlPerSeite;
# was auch immer hier folgen soll
$counter ++;
}
Für die Anpassung der Seitennummer und der Seitenposition an den Geschmack von Nichtprogrammierern kannst Du beiden gerne bei der Ausgabe eine 1 addieren. Sonst beginnen beide bei 0 zu zählen.
Tach!
Einführende Erläuterung: Zu den "echten Basics" zählt die strikte Trennung zwischen Daten, Programm und Darstellung. Berechenbare Darstellungsoptionen, die sich (womöglich sogar von Benutzer zu Benutzer oder Sitzung zu Sitzung (Bildschirmgröße -> Anzahl der Resultate je Seite) ändern können, haben definitiv nichts in der Datenbank zu suchen. Das betrifft hier also die Seitennummer und die Seitenposition.
Vorab: Es gibt auch keinen haltbaren Grund auf das "3. Resultat der 5. Seite" zugreifen zu wollen.
Das trifft nur zu, wenn der Anwendungsfall, den du dir gerade vorstellst, mit dem übereinstimmt, der beim Probleminhaber vorliegt. Er hat darüber außer Andeutungen nichts weiter verlauten lassen. Eine Beurteilung der Sinnhaftigkeit würde ich mir mangels Kenntnis des Anwendungsfalles nicht erlauben wollen.
dedlfix.
Eine Beurteilung der Sinnhaftigkeit würde ich mir mangels Kenntnis des Anwendungsfalles nicht erlauben wollen.
Ich sags mal so. Der Anwendungsfall, den ich mir gerade vorstelle, erscheint mir "stark überwiegend wahrscheinlich". Äußerdem versucht hier so mancher kleine Probleme auf eine irre komplizierte Weise zu lösen weil wer auch immer bei der Suche nach der Lösung seines Problems in eine Richtung gerannt ist, die Umkehr vermeiden will, und irgendwann aber feststellen muss, dass die Sonne morgens definitiv nicht im Westen steht.
Tach!
Eine Beurteilung der Sinnhaftigkeit würde ich mir mangels Kenntnis des Anwendungsfalles nicht erlauben wollen.
Ich sags mal so. Der Anwendungsfall, den ich mir gerade vorstelle, erscheint mir "stark überwiegend wahrscheinlich". Äußerdem versucht hier so mancher kleine Probleme auf eine irre komplizierte Weise zu lösen weil wer auch immer bei der Suche nach der Lösung seines Problems in eine Richtung gerannt ist, die Umkehr vermeiden will, und irgendwann aber feststellen muss, dass die Sonne morgens definitiv nicht im Westen steht.
Beachte bitte, dass das auch für Lösungsvorschläge gilt. Es wäre nicht das erst Mal, dass Lösungen mit sogar konkretem Code vorgestellt wurden, die dann doch nicht zum Problem passten. (Am besten fand ich immer die Schnellschüsse, die irgendeine in PHP vorhandene Funktionalität mit einem Kommandozeilenaufruf nachbauten.)
dedlfix.
Beachte bitte, dass das auch für Lösungsvorschläge gilt. Es wäre nicht das erst Mal, dass Lösungen mit sogar konkretem Code vorgestellt wurden, die dann doch nicht zum Problem passten.
Tja. Das ist dann wohl der Zeitpunkt an welchem der TO ( @Andy Nail ) beschreiben sollte, was er eigentlich vor hat und nicht nur das abstrakte Teilproblem an welchem er vermeintlich scheiterte.
Hello,
ich bitte um Entschuldigung für die folgenden starken Worte:
So einen Unsinn habe ich schon lange nicht mehr gelesen!
Andi Nail hat ziemlich exakt beschrieben, was er zu bauen gedenkt:
Was auch immer eine "Seite" hier ist (könnte eine Rechnung sein), was die Items sind, ist ziemlich klar. Es sind die Kinder der "Seite", also z. B. die Rechnungspositionen. Und wenn ich den Begriff "Item" hier selber einführe, dann deshalb, weil ich "Position auf der Seite" gar nicht anders deuten mag.
Es handelt sich hier augenscheinlich um ein klassisches Problem der Vorgangs- und Formularverarbeitung und warum sollte man das, auch wenn die Darstellung hier auf Webseiten stattfinden soll, nicht auch klassisch lösen? Es geht um Contents und ihre Zusammenhänge und nicht um Design oder Style.
Liebe Grüße
Tom S.
So einen Unsinn habe ich schon lange nicht mehr gelesen!
Unsinn? Fürwahr ein starkes Wort.
Was auch immer eine "Seite" hier ist (könnte eine Rechnung sein), was die Items sind, ist ziemlich klar. Es sind die Kinder der "Seite", also z. B. die Rechnungspositionen.
In dem Fall könnt es sich als positiv erweisen, sich ganz "oldstyle" an "Datenbanken -> Normalisierung" zu erinnern und also die Zuordnung der Rechnungspositionen zu den Rechnungen in getrennten Tabellen zu verwalten. Worauf hin sich das Problem "nur ein Autoinkrement" ganz locker in Luft auflöst. Soweit eine Paginierung/Sektionierung erforderlich ist, ist auch dann die von mir vorgestellte Lösung brauchbar.
Hello,
bist Du sicher?
Ich halte dagegen!
Das klassische Problem des (nicht temporär abhängigen) Einfügens in eine Position einer Liste (Tabelle) bleibt.
Liebe Grüße
Tom S.
Das klassische Problem des (nicht temporär abhängigen) Einfügens in eine Position einer Liste (Tabelle) bleibt.
Wir wissen halt nur nicht abschließend, ob dieses Problem hier wirklich das Problem ist.
bist Du sicher?
Man kann sich nie sicher sein so lange man sich an einem von einem anderem atomisierten und abstrahiertem statt dem konkreten Problem abarbeitet. Aber was die Normalisierung betrifft bin ich mir sicher. Das ist einfach mal eine Grundregel die fast den Charakter eines Naturgesetzes hat.
Doch brauche ich noch ein weiteres Feld das weiterzählt und die Position auf der Seite bestimmt.
Nein. Braucht Du nicht.
Vorliegend können die sich ändern und man die nämlich leicht und sehr schnell bei der Ausgabe berechnen.
Für die Anpassung der Seitennummer und der Seitenposition
Er hat nirgends geschrieben, dass er eine Ergebnismenge auf mehrere Seiten verteilen will. Ganz im Gegenteil, ich hebe es mal hervor:
auf meiner Seite brauche ich einmal ein Feld das automatisch weiterzählt wenn ein neuer Eintrag hinzugefügt wird
Entweder hat er nur eine Seite (URL) oder er meint mit "Seite" ganz allgemein den Dienst, die Webseite(n), die Site, eben die "Seite", wie das landläufig halt so üblich ist, wenn auch für das Problem nicht sonderlich präzise beschrieben.
Du scheinst hier die Einzige zu sein, die nicht verstanden hat, dass es ihm darum ging, Einträge automatisch nach Eingang zu sortieren, aber auch manuelle Korrekturen vornehmen zu können. Nicht mehr, nicht weniger.
Also im Hinblick auf Deinen Benutzername liegt es wohl an den Genen, dass Du um 19:19 noch immer - und nicht mit wohlwollenden Worten - spekulierst nachdem ich um 13:40 den TO darum gebeten habe, sich zu seinem Vorhaben zu äußern. Bis er das getan hat mache ich jedenfalls Pause.
Übrigens war ich zwischendrin schwimmen. Die damit verbundene Abkühlung kann ich ebenso wärmstens empfehlen wie das durch die Sonne gebildete Bee-Cool-Vitamin.
Also im Hinblick auf Deinen Benutzername liegt es wohl an den Genen, dass Du um 19:19 noch immer - und nicht mit wohlwollenden Worten - spekulierst nachdem ich um 13:40 den TO darum gebeten habe, sich zu seinem Vorhaben zu äußern.
Es liegt wohl eher an meinen hellseherischen Fähigkeiten, dass mein Kommentar noch angebracht ist, denn auch um 19:46 Uhr zeigst du immer noch nicht die Einsicht, dass deine groß aufgefahrene Zurechtweisung, auf der du eineinhalb Stunden lang rumgeritten bist, auf reichlich tönernen Füßen steht, und schiebst lieber dem Fragenden den Schwarzen Peter zu.
das durch die Sonne gebildete Bee-Cool-Vitamin.
Aha, kühle Bienen. Dann mal los :>