Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Variable in Function (https://www.delphipraxis.net/180837-variable-function.html)

Nersgatt 23. Jun 2014 06:47

Datenbank: MySql • Version: 5.6 • Zugriff über: egal

Variable in Function
 
Moin,

ich arbeite mich grade in MySql ein.
Ich möchte eine Function erstellen, die aus einer Tabelle den aktuellen Wert holt, den Wert in der Tabelle hochzählt und den geholten Wert zurückgibt.

Folgende Function hab ich erstellt:
Code:
CREATE DEFINER=`root`@`localhost` FUNCTION `get_next_id`() RETURNS int(11)
BEGIN
declare result int;

   select SEQUENCE_VALUE into @result from openjpa_sequence_table where id = 0;

   if (@result is null) then
      SET @result := 1;
      insert into openjpa_sequence_table (ID, SEQUENCE_VALUE) VALUES (0, 1);
   else    
      update openjpa_sequence_table
      set SEQUENCE_VALUE = SEQUENCE_VALUE + 1
      where ID = 0;
   end if;

   RETURN @result + 1;
END
Wenn ich die Function ausführe:
Code:
select @get_next_id;
bekomme ich immer NULL als Result zurück. Ich bin ratlos, warum das so ist. In der Tabelle sind aktuell keine Datensätze, daher sollte die Function den entsprechenden Datensatz erstellen.
In der Tabelle wird aber kein Datensatz erstellt. Daher vermute ich, dass der TRUE-Teil des If-Statements nicht ausgeführt wird.

Ich bin ratlos...

Dejan Vu 23. Jun 2014 07:03

AW: Variable in Function
 
Auch wenn es nicht hilft. Im Falle '@Result is null' musst du @Result auf 0 setzen (und nicht auf 1).

himitsu 23. Jun 2014 07:33

AW: Variable in Function
 
Du suchst also eine Lösung für das "INSERT OR UPDATE"-Problem?

Bei Google suchenMySQL INSERT OR UPDATE
http://dev.mysql.com/doc/refman/5.1/...duplicate.html


Postgre SQL kennt z.B. die Variable FOUND, welche auf True steht, wenn z.B. ein vorheriges Update mindestens einen Datensatz "fand".
Eventuell hat mySQL auch sowas oder was Ähnliches?
SQL-Code:
UPDATE db SET b = data WHERE a = key;
IF not FOUND THEN
  INSERT INTO db (a, b) VALUES (key, data);

Oder man macht sich selber soeine Variable, wenn die vorhandene Variable (hier @Result) kein passendes Ergebnis liefert.
SQL-Code:
declare result int;
declare jupp bool;
select SEQUENCE_VALUE, true into @result, @jupp from openjpa_sequence_table where id = 0;
if jupp is null then
  insert ...
else
  update ..
PS: Was passiert wohl, wenn zwischen dem SELECT und dem INSERT/UPDATE jemand Anderes ein INSERT/UPDATE macht?
Oder führt MySQL diese FUNCTION quasi atomar aus, so daß kein Anderer zur selben Zeit was an der Tabelle machen kann?

gravedigger 23. Jun 2014 08:11

AW: Variable in Function
 
Hallo Nersgat,

warum deklarierst du eine Variable Result und benutzt sie dann nicht?
Code:
CREATE DEFINER=`root`@`localhost` FUNCTION `get_next_id`() RETURNS int(11)
BEGIN

declare result int;

   select SEQUENCE_VALUE into result from openjpa_sequence_table where id = 0;

   if (result is null) then
      SET result := 1;
      insert into openjpa_sequence_table (ID, SEQUENCE_VALUE) VALUES (0, result);
   else  
      SET result := result+1;
      update openjpa_sequence_table
      set SEQUENCE_VALUE = result
      where ID = 0;
   end if;

   RETURN result;
END
sollte funktionieren.

Und wenn du jetzt noch ein Select auf die Funktion und nicht auf eine Variable machst sollte es erst recht funktionieren
Code:
select get_next_id();
Gruß aus Dortmund

Nersgatt 23. Jun 2014 08:38

AW: Variable in Function
 
Erst einmal danke für die Antworten!

@gravedigger: ich dachte, das hätte ich getan? :gruebel:
Wie würde ich den die von mir declarierte Variable referenzieren?

gravedigger 23. Jun 2014 08:48

AW: Variable in Function
 
Hallo Nersgatt,

die Variable @result ist eine Benutzervariable und muss nicht deklariert werden.
Sie behält ihren Wert solange wie die MySQL-Session geöffnet ist und nicht überschrieben wird.

So wie die Variable deklariert wurde sollte man sie auch benutzen
Code:
DECLARE result int;
SET result := result+1;
Gruß aus Dortmund

Nersgatt 23. Jun 2014 08:56

AW: Variable in Function
 
Ah, mir war das Konzept dieser Benutzervariablen nicht geläufig. Das erklärt meine Fehler.
Jetzt funktioniert es so wie gewünscht! :thumb:

@Dejan Vu: Deinen Hinweis hab ich natürlich auch gesehen und Du hast natürlich recht.

Danke!

Dejan Vu 23. Jun 2014 11:32

AW: Variable in Function
 
Fein, und ich hab was über mysql gelernt.

p80286 23. Jun 2014 11:55

AW: Variable in Function
 
Also abgesehen davon, daß
Code:
declare result int;
hier überfüssig ist
Code:
CREATE DEFINER=`root`@`localhost` FUNCTION `get_next_id`() RETURNS int(11)
 BEGIN
 declare result int;
 
   select SEQUENCE_VALUE into @result from openjpa_sequence_table where id = 0;
 
   if (@result is null) then
       SET @result := 1;
       insert into openjpa_sequence_table (ID, SEQUENCE_VALUE) VALUES (0, 1);
    else  
       update openjpa_sequence_table
       set SEQUENCE_VALUE = SEQUENCE_VALUE + 1
       where ID = 0;
    end if;
 
   RETURN @result + 1;
 END
sollte doch mit einem
Code:
select get_next_id ....
alles funktionieren, oder hab ich da etwas falsch verstanden?

Gruß
K-H

P.S. soetwas wie SQUENCES oder AUTOINC gibt es in MySQL nicht?

Nersgatt 23. Jun 2014 12:04

AW: Variable in Function
 
Zitat:

Zitat von p80286 (Beitrag 1263234)
P.S. soetwas wie SQUENCES oder AUTOINC gibt es in MySQL nicht?

Um den Hintergrund zu erklären: auf die DB greife ich aus Delphi heraus mit UniDAC zu. Gleichzeitig greifen aber auch Kollegen auf die Datenbank mit Java zu. Die Kollegen verwenden ein Persistenzframework (*), welches die Vergabe der IDs eben mit dieser Tabelle realisiert hat.
Damit es hier nicht zu Kollisionen kommt, ahme ich auf diese Weise das Verhalten des Persistenzframeworks nach.

(*) http://de.wikipedia.org/wiki/Apache_OpenJPA

himitsu 23. Jun 2014 12:04

AW: Variable in Function
 
Zitat:

Zitat von p80286 (Beitrag 1263234)
P.S. soetwas wie SQUENCES oder AUTOINC gibt es in MySQL nicht?

http://dev.mysql.com/doc/refman/5.1/...increment.html

[edit]
hmmmm :gruebel:

Dejan Vu 23. Jun 2014 12:09

AW: Variable in Function
 
[QUOTE=Nersgatt;1263235...Die Kollegen verwenden ein Persistenzframework (*), welches die Vergabe der IDs eben mit dieser Tabelle realisiert hat...[/QUOTE] Es sollte ein Gesetz gegen diesen Blödsinn geben. Das ist so dermaßen lahm... Egal. Esis wie esis

Nersgatt 23. Jun 2014 12:15

AW: Variable in Function
 
Zitat:

Zitat von Dejan Vu (Beitrag 1263238)
Zitat:

Zitat von Nersgatt (Beitrag 1263235)
...Die Kollegen verwenden ein Persistenzframework (*), welches die Vergabe der IDs eben mit dieser Tabelle realisiert hat...

Es sollte ein Gesetz gegen diesen Blödsinn geben. Das ist so dermaßen lahm... Egal. Esis wie esis

Auf welchen Aspekt beziehst Du Dich jetzt? Auf die Verwendung eines Persistenzframeworks, oder auf die Art und weise, wie die IDs verwaltet werden?
Ich finde es auch unglücklich, dies mit einer Tabelle zu machen, wenn die Datenbank dafür besser geeignete Mechanismen anbietet (wie z.B. Sequences). Aber in meinem Fall sind es halt Gegebenheiten, mit denen ich leben muss.

jaevencooler 23. Jun 2014 14:22

AW: Variable in Function
 
Moin, Moin,

ich habe auf meiner mySQL Instance die fehlenden Sequencen aus der Oracle wie folgt "ersetzt" :
Code:
DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `nextval`(`seq_name` varchar(100)) RETURNS bigint(20)
BEGIN
  declare cur_val bigint(20);

  SELECT sequence_cur_value
  INTO cur_val
  FROM gemiii.sequence_data
  WHERE sequence_name = seq_name;

  IF cur_val IS NOT NULL THEN
    UPDATE gemiii.sequence_data
    SET sequence_cur_value = IF ( (sequence_cur_value + sequence_increment) > sequence_max_value,
                                  IF ( sequence_cycle = TRUE,
                                       sequence_min_value,
                                       NULL
                                     ),
                                  sequence_cur_value + sequence_increment
                                )
    WHERE sequence_name = seq_name;
  END IF;

  RETURN cur_val;
END

die Tabelle dazu sieht folgt aus :

CREATE TABLE `sequence_data` (
  `sequence_name` varchar(100) NOT NULL,
  `sequence_increment` int(11) unsigned NOT NULL DEFAULT '1',
  `sequence_min_value` int(11) unsigned NOT NULL DEFAULT '1',
  `sequence_max_value` bigint(20) unsigned NOT NULL DEFAULT '18446744073709551615',
  `sequence_cur_value` bigint(20) unsigned DEFAULT '1',
  `sequence_cycle` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`sequence_name`),
  UNIQUE KEY `sequence_name_UNIQUE` (`sequence_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
funktioniert recht gut !

Beste Grüße Michael

Dejan Vu 24. Jun 2014 07:49

AW: Variable in Function
 
Zitat:

Zitat von Nersgatt (Beitrag 1263242)
Zitat:

Zitat von Dejan Vu (Beitrag 1263238)
Es sollte ein Gesetz gegen diesen Blödsinn geben. Das ist so dermaßen lahm... Egal. Esis wie esis

Auf welchen Aspekt beziehst Du Dich jetzt? Auf die Verwendung eines Persistenzframeworks, oder auf die Art und weise, wie die IDs verwaltet werden?...

Natürlich nur, wie die IDs verwaltet werden. Aber ich schrieb ja auch: 'Esis wie esis'. ('Es ist, wie es ist').


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:24 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz