Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: dziwne naruszenie integralności bazy - jak uniknąć omijania NOT NULL
Forum PHP.pl > Forum > Bazy danych
jolam
Mam taki problem. Podczas dodawania rekordów do tabeli w formularzu przypadkiem nie wypełniłam wszystkich pól. Tabela ma zdefiniowana każda kolumnę jako NOT NULL. I okazało się, że dodanie wiersza z pustymi łańcuchami (wydaje mi się, że puste pole przekazane przez formularz to właśnie taki pusty łańcuch) przeszło przez zabezpieczenie bazy o tych niezerowych kolumnach.
Jak tego uniknąć?

pozdrawiam serdecznie Jola
phpion
Wartość NULL to nie jest pusty string! Pusty string jest każdy inny string; tyle tylko, że jest pusty smile.gif Jako ciekawostkę powiem Ci jeszcze, że porównanie NULL = NULL zawsze zwróci fałsz. Dlaczego? Bo NULL to wartość, której nie można określić, takie nic. W związku z tym, skoro nie można określi wartości NULL, to nie można jej porównać z inną wartością NULL.
and_woj
Użytkownik phpion już wyjaśnił, że NULL nie oznacza pustego (niewypełnionego) pola, a wartość "nic". Analogicznie NOT NULL nie zapewni, że do pola tabeli nie da się zapisać pustego łańcucha znaków. W opisanym problemie najlepiej programowo sprawdzić w procedurze zapisującej rekord, czy wypełnione są wszystkie wymagane pola i w zależności od tego utworzyć (lub nie) rekord w tabeli. Nie przychodzi mi do głowy żaden sposób, aby załatwić problem samym SQLem.
jolam
Jeśli nie w SQL to w PHP. Jak Wy to rozwiązujecie, żeby Wam nie psuły takie przypadki bazy?

Pozdrawiam Jola
maly_swd
w php:

  1. if($_POST['pole_z_formularza_ktore_nie_moze_byc_puste']) {
  2. //oczywiscie spacja to juz nie jest puste pole
  3.  
  4. tu wykonujesz wstawienie do bazy danych
  5.  
  6. } else {
  7.  
  8. echo "pole z formularza jest puste, nic nie rob";
  9.  
  10. }
vokiel
  1. if (!empty($_POST['pole'])){
  2. // ok
  3. }
  4.  
  5. if (isset($_POST['pole'])){
  6. // ok
  7. }
jolam
To jak lepiej zrobić? Powinnam użyć isset czy !empty?

Pozdrawiam Jola
piotrooo89
ja w 90% przypadkach używam empty. tylko w 10% używam isset, jest to sporadyczne i podyktowane rożnymi specjalnymi okolicznościami.
phpion
Używanie empty() może czasem prowadzić do dziwnych sytuacji. Przykładowo: jeżeli w formularzu wpisujesz wielkość rabatu (wartość <0, 100>) to nie będzie można podać wartości 0, gdyż będzie ona traktowana przez empty() jako pusta. Listę wartości, jakie są uważane za puste znajdziesz w dokumentacji empty w sekcji Return Values.
piotrooo89
i to jest właśnie to 10% przypadków w których używam isset. dzięki ~phpion że o tym wspomniałeś. ważna sprawa.
thek
To może ja dorzucę Joli dlaczego stało się tak jak mówi. W momencie gdy przesłałaś zawartość formularza na serwer nie wiedziałaś, że niewypełnione pola tekstowe także zwracają pewną wartość, o której nie wiesz. To tak zwany znak końca łańcucha. To jeden z niedrukowalnych znaków o jakim wielu początkujących z programowaniem nie wie, ale bardzo szybko się dowiaduje winksmiley.jpg Zwłaszcza gdy się w C i C++ operuje na ciągach znakowych char*, bo mają one wtedy ogromne znaczenie i zapomnienie o nich potrafi mieć nieprzyjemne konsekwencje. W notacjach jest on zapisywany jako zero poprzedzone ukośnikiem, czyli \0, ale w formularzu podczas przesyłu nieco inaczej -> 0\' i możesz to zobaczyć podglądając zmienne POST. Jak więc widzisz, nie ma tam pustki tak naprawdę, i dlatego baza zapisuje go. To, że nic nie widzisz, nie znaczy, że nic tam nie ma winksmiley.jpg Dlatego jeśli chcesz mieć pewność, że takie coś Ci nie przejdzie to użyj sprawdzenia używając empty() smile.gif
wlatanowicz
Nie za bardzo rozumiem, dlaczego za spójność danych w bazie ma odpowiadać PHP.
Może warto zainteresować się więzami integralności? W tym przypadku należy zadbać o integralność krotki.
Służy do tego CHECK http://www.w3schools.com/Sql/sql_check.asp
Czyli oprócz NOT NULL należy dodać CHECK ( LENGTH( atrybut ) > 0 ) - przy założeniu, że funkcja LENGTH() zwraca długość ciągu znaków
thek
Dlaczego php? Bo skoro dane idą z formularza do bazy, to lepiej już na poziomie obróbki tych danych wyłapać problem niż pozwolić by poszło do bazy i czekać czy baza zwróci problem. Błędy powinno się eliminować w jak najwcześniejszym stadium.

EDIT: Nie dopisałem dlaczego tak uważam... Czasem połączenie z bazą jest wykonywane dla innego serwera niż ten, na którym jest cała strona (rzadkie przypadki, ale jednak). A podejście polegające na zrzucaniu check na bazę zamiast do skryptu wydłuży generowanie całości o czas łączenia z innym serwerem i czas na zwrócenie informacji.
vokiel
Cytat(jolam @ 23.10.2009, 07:30:36 ) *
To jak lepiej zrobić? Powinnam użyć isset czy !empty?

Pozdrawiam Jola


isset sprawdza, czy zmienna została zadeklarowana, empty sprawdza jej wartość. Jak już pisali poprzednicy dla 0 pomimo, że jest jakąś wartością empty zwróci false.

isset jest dobre w celu zorientowania się, czy pola w ogóle zostały wypełnione, albo jakie pola zostały przesłane. Empty może czasem napsuć nerwów, zwykle, gdy używa się go do sprawdzenia czy formularz został wysłany, sprawdzając $_POST z nazwą pola formularza (samego formularza), które nie ma przypisanego value. Niby formularz wysłany, var_dump pokazuje, że jest, a if'a nie przechodzi biggrin.gif
jolam
Bardzo wam wszystkim dziękuję za odpowiedź!
Szczególnie możliwość stosowania check w definicji bazy danych bardzo mi się podoba smile.gif

Pozdrawiam serdecznie Jola
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.