Bestimmten Datensatz aus sql-tabelle auslesen? aber wie?

Alles, was PHP betrifft, kann hier besprochen werden.

Bestimmten Datensatz aus sql-tabelle auslesen? aber wie?

Postby Anderswelt » 16. November 2006 00:37

Hallo mal wieder,

ich hänge momentan an folgendem Problem. Ich habe eine Artikelliste-Tabelle erstellt, die folgende (für meine weiteren Operationen relevanten) Felder enthält: id(Primärschlüssel), artikel_nr.
Nun ist es ja so, dass die id automatisch erhöht wird und nach dem löschen eines Datensatz keine durchgehende Reihe mehr entsteht:

1
2
3
4
(5 gelöscht)
6
7
...

Nun soll die Artikelnummer der letzten reihe ausgelesen und automatisch um 1 erhöht werden, wenn ich neue Datensätze hinzufüge.
Ich versuche nun zuerst die Anzahl der Datensätze auszulesen:

Code: Select all
[...]
$res = mysql_query("SELECT id, artikel_nr FROM artikelliste");
$rows = mysql_num_rows($res);


Im Grunde möchte ich nun jetzt dass er in etwa so etwas macht:

"Gib mir die artikel_nr der durch $rows = mysql_num_rows($res) ermittelten letzten reihe wieder, erhöhe sie um 1 und speichere sie in variable"

Vielen Dank schon mal für die Antworten

Anderswelt
Anderswelt
 
Posts: 9
Joined: 14. November 2006 00:49

Postby Hanspeter Thöni » 16. November 2006 08:59

Nun die höchste Artikel-Nummer zu kriegen ist relativ einfach
Code: Select all
select max(Artikelnummer) as High_Nr from artikelliste


Damit bekommst du im Resultat eine Zeile mit dem Feld High_Nr welche die höchste Artikelnummer enthält.

Generell aber gibt es mit diesem Vorgehen Stolperfallen:

A) Die Sache ist (bei grossen Tabellen) nicht besonders performant, da der höchste Wert gesucht werden muss)

B) Wenn zwei Benutzer zeitgleich einen Artikel anlegen erhalten bei der Abfrage beide die gleiche Zahl und somit die gleiche Artikelnummer!

Lösungsvorschläge für dieses Problem:
1. Anstelle einer separaten Artikelnummr die ID nehmen, die Datenbank kümmert sich dann darum dass korrekt hochgezählt wird.
2. Die höchste Artikelnummer in einer separaten Tabelle speichern (Nummernkreistabelle). Beim erhöhen der Zahl muss dann einfach der Datensatz gesperrt werden (select for update) um sicherzustellen, dass jeder eine frische Nummer bekommt.
3. Mittels direktem Nachlesen in der Artikeltabelle würde es schon auch gehen, aber die Tabelle muss dann komplett gesperrt werden um auch sicher die höchste Nummer zu erhalten.

Frühe oder späte Nummernvergabe. Frühe Nummernvergabe bedeutet, dass der Beutzer die Artikelnummer am Anfang der Transatkion bereits bekommt, bevor er die weiteren Daten einträgt. Nachteil: Speichert er den Artikel nicht ab, ist die Nummer halt verloren.
Bei Später Nummernvergabe wird die Nummer erst beim Speichern vergeben und dem Benutzer dann angezeigt.

Frühe Vergabe: Nur mit Variante 2 machbar, da die Tabelle ja nicht solange gesperrt werden kann.

Späte Vergabe: mit allen Varianten machbar.
Gruss Hanspeter
User avatar
Hanspeter Thöni
 
Posts: 233
Joined: 17. August 2004 10:29
Location: Schweiz

Postby kekster » 16. November 2006 14:44

Hanspeter Thöni wrote:A) Die Sache ist (bei grossen Tabellen) nicht besonders performant


Vielleicht zu simpel, aber vielleicht (?) schneller?

Code: Select all
SELECT id FROM db ORDER BY id DESC LIMIT 0, 1


Gruß
Hinzufallen ist keine Schande - Liegen zu bleiben dagegen verachtenswert
kekster
 
Posts: 19
Joined: 15. November 2006 10:28
Location: Paderborn

Postby Hanspeter Thöni » 16. November 2006 15:54

Stimmt, ist besser. Löst aber die anderen Probleme auch nicht.
Gruss Hanspeter
User avatar
Hanspeter Thöni
 
Posts: 233
Joined: 17. August 2004 10:29
Location: Schweiz

Postby Anderswelt » 16. November 2006 22:23

Ich hab das Problem jetzt für mich so gelöst:

Formulardatei:
Code: Select all
<?
 include("check_art_id.inc.php");
?>
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Artikel anlegen</title>
<meta name="author" content="Anderswelt">
</head>
<body>

<form action="insert_dataset.php" method="POST">
 <table align="center" border="1">
  <tr>
   <td colspan="2" align="center"><u><h2>Artikel eingeben</h2></u></td>
  </tr>
  <tr>
   <td>Artikelnummer:</td>
   <td align="right"><input type="Text" name="artikel_nr" value="<? echo $art_id ?>" size="6" maxlength="6"></td>
  </tr>
  <tr>
   <td>Bezeichnung:</td>
   <td align="right"><textarea name="bezeichnung" cols="25" rows="4"></textarea></td>
  </tr>
  <tr>
   <td>Kategorie:</td>
   <td align="right"><input type="text" name="kategorie"></input></td>
  </tr>
  <tr>
   <td>Einkaufspreis:</td>
   <td align="right"><input type="text" name="EK_preis"></input></td>
  </tr>
  <tr>
   <td>IST Anzahl:</td>
   <td align="right"><input type="text" name="IST"></input></td>
  </tr>
  <tr>
   <td>SOLL Anzahl:</td>
   <td align="right"><input type="text" name="SOLL"></input></td>
  </tr>
  <tr>
   <td>Versandart:</td>
   <td align="right"><input name="versand_art" size="1" value="DHL"></input></td>
  </tr>
  <tr>
   <td>Stammartikel Nr:</td>
   <td align="right"><input type="text" name="stamm_nr" size="8"></input></td>
  </tr>
  <tr>
   <td><input type="Submit" name="" value="Daten senden"></td>
   <td align="right"><input type="reset"></td>
  </tr>
 </table>
</body>
</html>


check_art_id.inc.php:
Code: Select all
<?
 require_once("_connect.inc.php");

 $result = mysql_query("SELECT * FROM artikelliste ORDER BY id DESC LIMIT 0,1");
 $res = mysql_fetch_array($result);

 if(is_array($res))
  {
   $artikel_id = $res[id]+1;
   $fill = substr("00000",strlen($artikel_id));
   $art_id = "1"."$fill"."$artikel_id";
  }
 else
  {
   $art_id = "100001";
  }
?>


und die tatsächliche Eingabe mit der Artikelnummer-Kollisionsabfrage:
Code: Select all
<?
 require_once("_connect.inc.php");

 $artikel_nr = $_POST["artikel_nr"];
 $bezeichnung = $_POST['bezeichnung'];
 $kategorie = $_POST['kategorie'];
 $EK_preis = preg_replace("/,/",".", $_POST['EK_preis']);
 $IST = $_POST['IST'];
 $SOLL = $_POST['SOLL'];
 $versand_art = $_POST['versand_art'];
 $stamm_nr = $_POST['stamm_nr'];

 $res = mysql_query("SELECT artikel_nr FROM artikelliste WHERE artikel_nr = $artikel_nr");
 $check_art_id = mysql_fetch_array($res);

 if(is_array($check_art_id) && in_array($artikel_nr, $check_art_id))
  {
   $art_nr = $artikel_nr+1;
  }
 else
  {
   $art_nr = $artikel_nr;
  }

   mysql_query("INSERT INTO artikelliste VALUES (
                         '',
                         '$art_nr',
                                                '$bezeichnung',
                                                '$kategorie',
                                                '$EK_preis',
                                                '$IST',
                                                '$SOLL',
                                                '$versand_art',
                                                '$stamm_nr');");

?>
 <a href="insert_data.php">Neueingabe</a>


Vielleicht hat jemand ja noch Verbesserungsvorschläge, wie man es eleganter gestalten kann. Diese Eingabe bezieht sich erst mal nur auf die Tabelle artikelliste; weitere Schritte sind das hinzufügen einer Kategorie_id, die ich mit der Kategorie aus der Kategorie Tabelle ziehe. Dabei wird dann anhand der Kategorie_id die Anfangszahl der Artikelnummer bestimmt werden.
Anderswelt
 
Posts: 9
Joined: 14. November 2006 00:49


Return to PHP

Who is online

Users browsing this forum: No registered users and 4 guests