Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Pobranie 1 wolnego id z pola typu auto_increment
Forum PHP.pl > Forum > Bazy danych > MySQL
Ania-678
Witam.
Jestem na tym forum nowa i przejdę do sedna sprawy...

Otóż jest Mi potrzebne funkcja która Mi pobierze pierwszy WOLNY numer rekordu z pola typu auto_increment.

I w zasadzie to chyba znalazłam co Mnie potrzeba -> http://algorytmy.pl/?id=1064&pp=503

Ale jest małe ale:

UWAGA! To tylko fragment strony! Całą zobaczysz po opłaceniu abonamentu! ohmy.gif

A trochę dużo tam wołają za SMS'a zaś karty nie posiadam...

Może ktoś zna inne miejsce gdzie to znajdę albo Sam też wie jak takie coś napisać bo jest Mi bardzo potrzebne.

EDIT: Pracuję na php 4/5 oraz mysql 4.1.21-standard

Pozdrawiam i czekam na pomoc smile.gif
Cienki1980
Jeżeli potrzebujesz następnego id z pola auto_increment wystarczy jak zapytasz bazę o maksymalną wartość tego pola MAX(id) i w php dodasz +1 ... otrzymasz wartość najbliższego wpisu w tą kolumnę.

Nie wiem do czego jest Ci to potrzebne ale zakładam, że chcesz to nowe ID wpisać gdzieś do innej tabeli tak, żeby mieć połączenie między tabelami. Jeżeli takie coś chcesz wykonać, możesz odwrócić sytuację i dodać wiersz do tabeli pierwszej po czym za pomocą mysql_insert_id" title="Zobacz w manualu PHP" target="_manual pobrać wygenerowaną wartość pola ID.
sticker
pierwszy wolny to znaczy ten który bedzie wstawiony nastepnym razem dobrze rozumiem ?

  1. SELECT max(id) FROM TABLE


chyba że chodzi Ci o pierwszy biorąc pod uwage też usunięte rekordy, ale to rozwiązanie ma zbyt wiele wad zeby je wykorzystywac
skowron-line
Cytat(sticker @ 15.06.2007, 10:20:47 ) *
chyba że chodzi Ci o pierwszy biorąc pod uwage też usunięte rekordy, ale to rozwiązanie ma zbyt wiele wad zeby je wykorzystywac


dokladnie o to jej chodzi moze ktorys z was by zajrzal w lik ktory dala

jest cos takiego
Kod
+----+--------+----------+
| id | imie   | nazwisko |
+----+--------+----------+
|  1 | Julia  | Murek    |
|  2 | Robert | Kwak     |
|  5 | Jan    | Nowak    |
|  6 | Jan    | Kowal    |
|  7 | Anna   | Maliniak |
+----+--------+----------+
i jak widac brakuje nr 3

mozesz np pobrac max(id) a potem w petli sprawdzac czy takie id istnieje i jak nie to masz odpowiedz
SongoQ
Cytat
mozesz np pobrac max(id) a potem w petli sprawdzac czy takie id istnieje i jak nie to masz odpowiedz

Po co? Przeciez mozna max(id) + 1
skowron-line
Cytat(SongoQ @ 15.06.2007, 12:08:53 ) *
Po co? Przeciez mozna max(id) + 1


ale max(id) zwroci 7 a nie 2
Ania-678
Więc tak...

Nie chodzi Mnie o zmianę auto_increment tylko o wyszukanie tabelki pustych rekordów.

Mam na przykład taką tabelkę:

ID | user
----------
1 | fsdf
2 | bgfgt
3 | bvcfsd
5 | sdfss
6 | teregf

i chcę "wyciągnąć" najniższy puste miejsce z niej czyli w tym przypadku id 4.

Bo to Mnie potrzebne do skryptu rejestracji przez aktywację via mail i przy jego potwierdzeniu następuje taka akcja:

  1. <?php
  2. $aktiv = $db -> Execute("SELECT * FROM tabelka1 WHERE aktyw=".$_GET['kod']);
  3. $db -> Execute("INSERT INTO tabelka2 (user, email, pass) VALUES('".$aktiv -> fields['user']."','".$aktiv -> fields['email']."','".$aktiv -> fields['pass']."')");
  4. $db -> Execute("DELETE FROM tabelka1 WHERE aktyw=".$_GET['kod']);
  5. ?>


Oczywiście w tabeka2 jest pierwsze pole ID z auto_increment i zawsze id przy tym INSERTcie jest najwyższe id jakie już w niej jest + 1

Zaś Ja potrzebuję by INSERT "pakował" się do najniższego wolnego id w tabeka2

rolleyes.gif
SongoQ
aaaaa
@skowron-line Zle sobie odczytalem chodzilo mi o max

Rozwiazaniem jest proste. Chyba sie nie pomylilem bo z palca

  1. SELECT * FROM tabela t1 LEFT JOIN tabela t2 ON t1.id = t2.id + 1 WHERE t2.id IS NULL LIMIT 1
Ania-678
Cytat(SongoQ @ 15.06.2007, 14:37:15 ) *
aaaaa
@skowron-line Zle sobie odczytalem chodzilo mi o max

Rozwiazaniem jest proste. Chyba sie nie pomylilem bo z palca

  1. SELECT * FROM tabela t1 LEFT JOIN tabela t2 ON t1.id = t2.id + 1 WHERE t2.id IS NULL LIMIT 1



Operuję na jednej tabeli, a jak dobrze rozumiem to powyżej jest na dwie...
kwiateusz
źle rozumiesz to jest jedna tabela łączona z sama sobą t1 to "tabela" i tak samo t2 to "tabela" (jedna i ta sama)
Ania-678
To nie wiem czy dobrze podstawiam Swą nazwę tabelki:

  1. SELECT * FROM REJES t1 LEFT JOIN REJES t2 ON t1.id = t2.id + 1 WHERE t2.id IS NULL LIMIT 1


bo pokazuje Mi ciągle rekord o id 1 który JEST a najwyższy to mam ponad 14XX... dry.gif


EDIT:

po zwiększeniu LIMITu do 10

  1. SELECT *FROM players t1 LEFT JOIN players t2 ON t1 . id =t2 . id +1 WHERE t2 . id IS NULL ORDER BY `t1`.`id` ASC LIMIT 10


otrzymałam rekordy o id 1, 5, 9, 12, 15, 22, 25, 31, 34, 36

zaś w bazie pierwsze 10 rekordów to:

1, 2, 3, 5, 9, 10, 12, 15, 16, 17

Więc yyy... coś mnie tu nie pasuje...
superfrajer
Niezbyt dobrze kombinujesz

Dodaj do tabeli userow pole IsConfirmed
Przy rejestracji normalnie dodaj usera z polem IsConfirmed ustawionym na false

Zrob tabele ConfirmationCodes z
IdUser
ConfirmationCode

Po dodaniu uzytkownika dodaj nowy rekord do tej tabeli
z IdUser wzietym z mysql_insert_id()
wygenerowanym kodem np. md5(time() + IdUser)

Wyslij mu ten kod mailem.

Jak user kliknie na linka aktywacyjnego wybierz z tabeli rekord ktory ma taki sam ConfirmationCode
masz wtedy IdUser
Uaktualniasz rekord w tabeli usera zmieniajac IsConfirmed na true
A nastepnie usuwasz rekord z tabeli ConfirmationCodes gdzie IdUser jest rowne temu ktorego wybrales.

Tyle.

Pozdrawiam
Norbas
@superfrajer Jaki jest związek tego co napisałeś z tematem wątku, gdyż nie zrozumiałem

Odnośnie tematu wątku, to proponuję następujące zapytanie:
  1. SELECT id-1
  2. FROM rejs WHERE id>1 AND id-1 NOT IN (SELECT id FROM rejs) LIMIT 1

Jeżeli otrzymasz w wyniku zero rekordów, to oznacza, że rekordy są po kolei lub tabela jest pusta
Ania-678
No wynik jest pusty...

Ale... ja to potrzebuję do INSERTa, bo Ja nie wiem jak do Niego określić tym powyżej czy dane pole id jest puste czy też nie dry.gif
SongoQ
Myslalem ze po moim poscie poradzisz sobie.

Masz tutaj kompletne zapytanie ktore zwroci Ci doklanie 1 oczekiwana wartosc.

  1. SELECT t1.id + 1 FROM tabela t1 LEFT JOIN tabela t2 ON t1.id = t2.id + 1 WHERE t2.id IS NULL ORDER BY t1.id LIMIT 1
Ania-678
Ten dziad:

  1. $aktiv = $db -> Execute("SELECT * FROM ak WHERE aktyw=".$_GET['kod']);
  2. $fid = $db -> Execute("SELECT t1.id + 1 FROM akt t1 LEFT JOIN akt t2 ON t1.id = t2.id + 1 WHERE t2.id IS NULL ORDER BY t1.id LIMIT 1");
  3. $db -> Execute("INSERT INTO akt (id, user, email, pass) VALUES('".$fid."','".$aktiv -> FIELDS['user']."','".$aktiv -> FIELDS['email']."','".$aktiv -> FIELDS['pass']."')");
  4. $db -> Execute("DELETE FROM ak WHERE aktyw=".$_GET['kod']);


ma Mnie gdzieś i ciągle id = auto_increment z db... dry.gif
UDAT
Spróbuj
  1. SELECT t1.id+1 FROM tabela t1 WHERE NOT EXISTS (
  2. SELECT id FROM tabela WHERE id=t1.id+1
  3. ) ORDER BY t1.id LIMIT 1;
Ania-678
Ni jedno, ni drugie egzaminu nie zdaje...
superfrajer
Norbas: taki jest zwiazek, ze dziewczyna troche bez sensu kombinuje, przeczytaj caly temat dokladnie to zobaczysz.

Ania-678: jeszcze prostszym sposobem na aktywacje jest po prostu z rejestracji wywalic pole podawania hasla, i wygenerowac samemu haslo userowi i wyslac mu na maila. Odpada wtedy sprawdzanie kodow itd...

Pozdrawiam
UDAT
A to:
  1. SELECT IF(
  2. NOT EXISTS (
  3. SELECT id FROM tabela WHERE id=0
  4. ),
  5. 0,
  6. ( SELECT t1.id+1 FROM tabela t1
  7. WHERE NOT EXISTS (
  8. SELECT id FROM tabela WHERE id=t1.id+1
  9. ) ORDER BY t1.id LIMIT 1
  10. )
  11. );


Jeśli nie zadziała to powiedz co zwraca, bo mam zainstalowane MySQL 5.0.40
Ania-678
Po wywołaniu zapytania w PMA "sprzedał" Mi coś takiego:

  1. IF( NOT EXISTS ( SELECT id FROM akt WHERE id = 0 ) , 0 , ( SELECT t1 . id + 1 FROM akt t1 WHERE NOT EXISTS ( SELECT id FROM akt WHERE id = t1 . id + 1 ) ORDER BY t1 . id LIMIT 1 ) )
  2. 0


Zaś w skrypcie nie działa wciąż...

@superfrajer

nie chodzi Mnie o zadne kody aktywacji czy coś w tym kierunku tylko o INSERTowanie wartości do tabeli akt w PIERWSZE wolne id (auto_increment)...
SongoQ
2 razy odpowiedzialem na to pytanie. Problem jest w wyciagnieciu tej wartosci i wstawieniu do zapytania. Kazdy podaje swoja wersje po co? Tu nie chodzi teraz o zapytanie tylko przekazanie wartosci do zapytania.

Czytajcie posty od poczatku do konca. Kolejne takie wtracenia beda nagradzane banem.

  1. <?php
  2. $fid = $db -> Execute("SELECT t1.id + 1 AS kolejne_id FROM akt t1 LEFT JOIN akt t2 ON t1.id = t2.i
    d - 1 WHERE t2.id IS NULL ORDER BY t1.id LIMIT 1"
    );
  3. ?>


co zwraca $fid?? zrob print_r($fid)

  1. <?php
  2. $db -> Execute("INSERT INTO akt (id, user, email, pass) VALUES('".$wartosc_odczytana_z_wczesniejszego_zapytania."','".$aktiv -> fields['user']."','".$aktiv -> fields['email']."','".$aktiv -> fields['pass']."')");
  3. ?>


Czy tak trudno jest pokombinowac i zobaczyc co zwraca.
UDAT
Cytat(SongoQ @ 16.06.2007, 17:26:28 ) *
2 razy odpowiedzialem na to pytanie.
...
Czytajcie posty od poczatku do konca. Kolejne takie wtracenia beda nagradzane banem.


Tylko że twoje zapytanie jest błędne.
Dla danych, gdzie ID są w kolejności:
Kod
4
5
6
7


Powinien zwrócić 0, zwraca:
Kod
+------------+
| kolejne_id |
+------------+
|          5 |
+------------+
1 row in set (0.01 sec)
Kicok
To zadanie nie jest takie proste, jakie się wydaje na pierwszy rzut oka.

Ania-678: Przetestuj to zapytanie:

Kod
(
SELECT t1.id + 1 AS pusty_id
FROM tabela t1
WHERE (SELECT t2.id FROM tabela t2 WHERE t1.id = t2.id-1) IS NULL
)
UNION
(
SELECT MIN(id)-1 AS pusty_id
FROM tabela
HAVING pusty_id > 0
)
ORDER BY pusty_id ASC
LIMIT 1
UDAT
Cytat(Kicok @ 16.06.2007, 18:33:55 ) *
Kod
SELECT MIN(id)-1 AS pusty_id
FROM tabela
HAVING pusty_id > 0

Ta część zapytania pobierze jeden z niższych wyników, ale nie najniższy.
Dla danych:
Kod
4
5
6
7

zwróci 3, druga część zwróci 8, a powinno zwrócić 0. Tak więc nie podałeś rozwiązania.


Jedyne rozwiązanie, które działa jest przedstawione w moim poście, gdyż jeśli nie ma najmniejszej wartości to ją zwraca, jeśli nie to zwraca ID+1, którego nie ma w tabeli, sprawdzane dla każdego ID już istniejącego.
Kicok
Cytat("UDAT")
Jedyne rozwiązanie, które działa jest przedstawione w moim poście, gdyż jeśli nie ma najmniejszej wartości to ją zwraca, jeśli nie to zwraca ID+1, którego nie ma w tabeli, sprawdzane dla każdego ID już istniejącego.


A mógłbyś podać przykładowe wartości, dla których twoje zapytanie działa? Bo jak bym tego nie testował, to zawsze zwraca mi: 0. Nawet dla danych:
Kod
0
1
2
3
5
6



Jeśli używa się MySQL5 to najprostszym wyjściem będzie napisanie prostej funkcji:
Kod
DROP FUNCTION IF EXISTS pierwsze_puste_id;

DELIMITER $
CREATE FUNCTION pierwsze_puste_id() RETURNS INT
BEGIN

  SET @ID = 1;
  SET @MAX_ID = ( SELECT MAX(id) FROM tabela );

  WHILE( @ID <= @MAX_ID )
  DO
    IF NOT EXISTS ( SELECT id FROM tabela WHERE ( id = @ID ) ) THEN
      RETURN( @ID );
    END IF;

    SET @ID = @ID + 1;
  END WHILE;

  RETURN( @ID );

END$
DELIMITER;
(zakładamy że id ma być dodatnie)


No chyba, że jest w MySQL'u odpowiednik: range" title="Zobacz w manualu PHP" target="_manual - to wtedy wystarczyłoby zwykłe podzapytanie.
Ania-678
Już mam, znalazłam człowieka który miał konto na tamtej stronie i działa tongue.gif
UDAT
Cytat(Kicok @ 16.06.2007, 21:57:15 ) *
A mógłbyś podać przykładowe wartości, dla których twoje zapytanie działa? Bo jak bym tego nie testował, to zawsze zwraca mi: 0. Nawet dla danych:
Kod
0
1
2
3
5
6

Zero zwraca tylko gdy nie ma pola o ID = 0, inaczej zwraca pierwsze nie istniejące, o jeden większe od już wpisanego. A co do twojego przykładu, to zobacz co mi MySQL zwrócił:
Kod
mysql> SELECT * FROM tabela;
+----+
| ID |
+----+
|  0 |
|  1 |
|  2 |
|  3 |
|  5 |
|  6 |
+----+
6 rows in set (0.00 sec)

mysql> SELECT IF(
    ->     NOT EXISTS (
    ->         SELECT id FROM tabela WHERE id=0
    ->     ),
    ->     0,
    ->    ( SELECT t1.id+1 FROM tabela t1
    ->      WHERE NOT EXISTS (
    ->             SELECT id FROM tabela WHERE id=t1.id+1
    ->      ) ORDER BY t1.id LIMIT 1
    ->     )
    -> ) as empty;
+-------+
| empty |
+-------+
|     4 |
+-------+
1 row in set (0.00 sec)


Masz pomysł dlaczego u mnie działa, a u Ciebie nie?
Jeśli chcesz numerację od 1 to zmień w 3. i 5. linii 0 na 1
Kicok
Cytat
Masz pomysł dlaczego u mnie działa, a u Ciebie nie?


OK, już wiem o co chodziło. Kolumna z primary key nie przyjmuje zera - zamienia je od razu na kolejną liczbę (auto_increment), tak jakby się w ogóle tej wartości nie podawało. Dlatego zapytanie zawsze zwracało 0. Dla kolumny bez primary key wszystko działa w porządku.

Zgubił mnie MySQL Query Browser. Dodawałem rekordy metodą Access'ową (Edycja -> dopisywanie liczb -> Zastosuj zmiany). Wtedy 0 było normalnie wyświetlane. Dopiero po ponownym wykonaniu zaputania SELECT * FROM tabela zamieniało się na auto_incrementa
eai
Cytat
Już mam, znalazłam człowieka który miał konto na tamtej stronie i działa


Może się z nami podzielisz rozwiązaniem?
UDAT
Poprawiona wersja:
Kod
mysql> SELECT IF(
    ->     NOT EXISTS (
    ->         SELECT id FROM tabela WHERE id=1
    ->     ),
    ->     1,
    ->    ( SELECT t1.id+1 FROM tabela t1
    ->      WHERE NOT EXISTS (
    ->             SELECT id FROM tabela WHERE id=t1.id+1
    ->      ) ORDER BY t1.id LIMIT 1
    ->     )
    -> ) as empty;
eai
mysql> SELECT IF(min(id)<1,
-> 1,
-> ( SELECT t1.id+1 FROM tabela t1
-> WHERE NOT EXISTS (
-> SELECT id FROM tabela WHERE id=t1.id+1
-> ) ORDER BY t1.id LIMIT 1
-> )
-> ) as empty
-> FROM tabela;

mozna tez tak smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.