Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PostgreSQL][PHP] Problem z zapytaniem, projekt bazy danych
Forum PHP.pl > Forum > Przedszkole
Xenom
Korzystam z bazy danych postgresql, ale używam poradników z mysql i w razie błedów zapytań staram się poszukać informacji w google.
W poniższym przypadku trafiłem na nadmiar informacji i tutaj poproszę o pomoc. Przedstawię najlepiej cały kod z zakomentowaniem linijek dających błąd, to będzie mówić samo za siebie i więcej niż moje amatorskie wyjaśnienie.
Jest to mój pierwszy projekt bazy danych/php i za krytyczne uwagi będę wdzięczny (varchary nie są skonfigurowane).
  1. <?php
  2. require "db_conf.php";
  3. require "db_connect.php";
  4.  
  5. $create_users_table = pg_query('CREATE TABLE users (
  6. id_user BIGINT NOT NULL, //w tym wypadku nie SERIAL bo dla zwykłego usera bedzie korzystanie z konta facebook
  7. money FLOAT DEFAULT '0',
  8. name VARCHAR(20) DEFAULT 'none',
  9. mail VARCHAR(20) DEFAULT 'none',
  10. PRIMARY KEY (id_user)
  11. )');
  12.  
  13. $create_companies_table = pg_query('CREATE TABLE companies (
  14. login VARCHAR(20) NOT NULL, //też nie SERIAL, tylko login na pr.key, poniewaz wiekszosc zapytan bedzie szukac po loginie
  15. company_name VARCHAR(20) NOT NULL,
  16. regon VARCHAR(20) NOT NULL,
  17. nip VARCHAR(20) NOT NULL,
  18. krs VARCHAR(20) DEFAULT 'none',
  19. director VARCHAR(20) NOT NULL,
  20. adress VARCHAR(20) NOT NULL,
  21. city VARCHAR(20) NOT NULL,
  22. state VARCHAR(20) NOT NULL,
  23. phone VARCHAR(20) NOT NULL,
  24. mail VARCHAR(20) NOT NULL,
  25. password VARCHAR(20) NOT NULL,
  26. money FLOAT DEFAULT '0',
  27. active BOOL DEFAULT '0',
  28. PRIMARY KEY (login)
  29. )');
  30.  
  31. $create_products_table = pg_query('CREATE TABLE products (
  32. id_product BIGINT SERIAL NOT NULL, //bigint bo moze byc z czasem cala masa produktów/ jest cos takiego jak unsigned w cpp?
  33. login_seller VARCHAR(20) NOT NULL,
  34. normal_price FLOAT NOT NULL,
  35. promotion_price FLOAT NOT NULL,
  36. product_name VARCHAR(20) NOT NULL,
  37. description text NOT NULL,
  38. product_city VARCHAR(20) NOT NULL,
  39. start_date VARCHAR(20) NOT NULL,
  40. day_count INT NOT NULL,
  41. photo VARCHAR(20) NOT NULL,
  42. PRIMARY KEY (id_product),
  43. KEY (login_seller) //blad tutaj przy zapytaniu
  44. )');
  45.  
  46. $control_table = pg_query('CREATE TABLE control ( //ta tabela kotroluje jaki user, jaki produkt zakupil
  47. id_user BIGINT NOT NULL,
  48. id_product BIGINT NOT NULL,
  49. date VARCHAR(16) NOT NULL
  50. INDEX ('id_user','id_product') //blad tutaj przy zapytaniu
  51. )');
  52. ?>
czachor
Podaj komunikaty błędów, które się wyświetlają.
bpskiba
1.W przedostatniej linijce brakuje przecinka na końcu
2. W ostatniej linijce nie Index, a key lub Foreign key i brak definicji nazwy indexu
Xenom
Ok dzięki za radę, poradźcie mi teraz, czy tak wykonana db z referencjami jest dobrą konstrukcją, czy referencje poniżej nie powinny być umieszczane?
  1. <?php
  2. require "db_conf.php";
  3. require "db_connect.php";
  4.  
  5. $create_users_table = pg_query('CREATE TABLE users (
  6. id_user BIGINT NOT NULL,
  7. money FLOAT DEFAULT '0',
  8. name VARCHAR(20) DEFAULT 'none',
  9. mail VARCHAR(20) DEFAULT 'none',
  10. PRIMARY KEY (id_user)
  11. )');
  12.  
  13. $create_companies_table = pg_query('CREATE TABLE companies (
  14. login VARCHAR(15) NOT NULL,
  15. company_name VARCHAR(50) NOT NULL,
  16. regon VARCHAR(20) NOT NULL,
  17. nip VARCHAR(20) NOT NULL,
  18. krs VARCHAR(20) DEFAULT 'none',
  19. director VARCHAR(40) NOT NULL,
  20. adress VARCHAR(40) NOT NULL,
  21. city VARCHAR(20) NOT NULL,
  22. state VARCHAR(20) NOT NULL,
  23. phone VARCHAR(16) NOT NULL,
  24. mail VARCHAR(30) NOT NULL,
  25. password VARCHAR(20) NOT NULL,
  26. money FLOAT DEFAULT '0',
  27. active BOOL DEFAULT '0',
  28. PRIMARY KEY (login)
  29. )');
  30.  
  31. $create_products_table = pg_query('CREATE TABLE products (
  32. id_product SERIAL NOT NULL,
  33. login_seller VARCHAR(15) NOT NULL REFERENCES companies(login),
  34. normal_price FLOAT NOT NULL,
  35. promotion_price FLOAT NOT NULL,
  36. product_name VARCHAR(20) NOT NULL,
  37. description text NOT NULL,
  38. product_city VARCHAR(20) NOT NULL,
  39. start_date VARCHAR(16) NOT NULL,
  40. day_count INT NOT NULL,
  41. photo VARCHAR(50) NOT NULL,
  42. PRIMARY KEY (id_product)
  43. )');
  44.  
  45. $control_table = pg_query('CREATE TABLE control (
  46. id_user BIGINT NOT NULL REFERENCES users(id_user),
  47. id_product BIGINT NOT NULL REFERENCES products(id_product),
  48. date VARCHAR(16) NOT NULL
  49. )');
  50. ?>
bpskiba
Po mojemu jest to bardzo zła konstrukcja.
1. Kwestia porządku: Jeżeli tworzysz tabelę users, to kluczem powinno być id_users. Dla tabeli products id_products
2. Dla kluczy głównych obowiązkowo autoincrement
3. Za pomysł uczynienia kluczem głównym pola VARCHAR w tabeli companies należy Cię wybatożyć
4. Pola na pieniądze nie float, a numeric lub decymal
5. Pole na datę nie typu Varchar, a np DATETIME
6. Brak powiązań między tabelami
7. Takie dane jak telefon lepiej przechowywać w polach INT
8. Za mało kluczy zewnętrznych wymuszających więzy integralności
9. Widzę pole start_date. Jeżeli masz zamiar określać odstępy między datami, to obowiązkowo typ Timestamp
10. NIP, regon to pola typu INT (pomyśl jak będzie wyglądać wyszukiwanie po numerze nip)

W ramach higieny języka polskiego zapytam czemu te nazwy tabel są po angielsku.
Na osłodę dodam, że to są typowe błędy, które popełniał każdy (ze mną włącznie) aarambo.gif
Xenom
Cytat(bpskiba @ 19.04.2012, 18:17:12 ) *
Po mojemu jest to bardzo zła konstrukcja.
1. Kwestia porządku: Jeżeli tworzysz tabelę users, to kluczem powinno być id_users. Dla tabeli products id_products
2. Dla kluczy głównych obowiązkowo autoincrement
3. Za pomysł uczynienia kluczem głównym pola VARCHAR w tabeli companies należy Cię wybatożyć
4. Pola na pieniądze nie float, a numeric lub decymal
5. Pole na datę nie typu Varchar, a np DATETIME
6. Brak powiązań między tabelami
7. Takie dane jak telefon lepiej przechowywać w polach INT
8. Za mało kluczy zewnętrznych wymuszających więzy integralności
9. Widzę pole start_date. Jeżeli masz zamiar określać odstępy między datami, to obowiązkowo typ Timestamp
10. NIP, regon to pola typu INT (pomyśl jak będzie wyglądać wyszukiwanie po numerze nip)

W ramach higieny języka polskiego zapytam czemu te nazwy tabel są po angielsku.
Na osłodę dodam, że to są typowe błędy, które popełniał każdy (ze mną włącznie) aarambo.gif

Serdeczne dzięki, już piszę dlaczego, co i jak zrobiłem i też mam pytania.
1. tabela użytkowników będzie podłączona do facebooka i robiłem ja z zamysłem, że podczas logowania użytkownik będzie szukany
właśnie po tym id, w sensie że nadawanie jako główny klucz nowego id spowolni wyszukiwanie danych po logowaniu. Czy to dobre podejście, czy jednak
zwykły SERIAL i nowe id dodatkowo jako klucz główny?
2. autoincrement to nie jest przypadkiem SERIAL w postgresql?
3. Podczas logowania firm, czy wyświetlania formularzy bedzie wykorzystywany login, czy id_firma będzie lepsze. Moja logika polega na tym, że skrypt szuka tylko loginu
i nie musi sortować wszystkich danych(rozumiem, że klucz główny powoduje takie sortowanie), teraz jakbym miał znaleźć firme po id to DB musi jechać każde id pokolei.
Jak ten tok myślenia jest zły to też napiszcie, żebym zrozumiał dlaczego.
6. Nie bardzo rozumiem, mam pewne wyobrażenie jak ta aplikacja ma działać i na bazie czego pobierać dane z DB, to dałem pod tabelę control. W jakim sensie brak powiązań?

Resztę rozumiem, w każdym razie dzięki za rady.
Co do pytania o angielskie nazewnictwo, to jest to pewne przyzwyczajenie, mimo że mam taki sobie angielski. Od jakiegoś czasu zajmuję się tworzeniem gier free(aktualnie na fonline engine, angel script, który bardzo podobny jest do cpp) i współpracowałem z osobami z wielu krajów, dlatego ten angielski na siłę wbijam :-)

Co do tworzenia powyższej aplikacji to nie mam absolutnie doświadczenia w tej działce. Jest to aplikacja na życzenie szefa(choć firma nie zajmuje się programowaniem), więc w pracy muszę bardziej działać i staram się to jakoś ogarnąć, jednak wolę poświęcić dużo więcej czasu na fundamentalne konstrukcje typu DB i zrobić to jakoś przyzwoicie z Waszą pomocą.
Inna sprawa, że świetnie się przy tym bawię, a dodatkowo uczę nowych rzeczy, co daje mi przyjemność i radochę z pracy.

ps. Tu taki przykład gry http://www.youtube.com/watch?v=ZjA2wBU10z8...hwgWSDJZYVInzg= , gdzie właśnie z wykorzystaniem fonline engine staramy się przenieść realia fallouta 2 i tactics na mmo :-)
bpskiba
Cytat(Xenom @ 20.04.2012, 08:01:47 ) *
Serdeczne dzięki, już piszę dlaczego, co i jak zrobiłem i też mam pytania.
1. tabela użytkowników będzie podłączona do facebooka i robiłem ja z zamysłem, że podczas logowania użytkownik będzie szukany
właśnie po tym id, w sensie że nadawanie jako główny klucz nowego id spowolni wyszukiwanie danych po logowaniu. Czy to dobre podejście, czy jednak
zwykły SERIAL i nowe id dodatkowo jako klucz główny?
2. autoincrement to nie jest przypadkiem SERIAL w postgresql?
3. Podczas logowania firm, czy wyświetlania formularzy bedzie wykorzystywany login, czy id_firma będzie lepsze. Moja logika polega na tym, że skrypt szuka tylko loginu
i nie musi sortować wszystkich danych(rozumiem, że klucz główny powoduje takie sortowanie), teraz jakbym miał znaleźć firme po id to DB musi jechać każde id pokolei.
Jak ten tok myślenia jest zły to też napiszcie, żebym zrozumiał dlaczego.
6. Nie bardzo rozumiem, mam pewne wyobrażenie jak ta aplikacja ma działać i na bazie czego pobierać dane z DB, to dałem pod tabelę control. W jakim sensie brak powiązań?

Ad. 1 Dwa problemy
- facebook jak i wiele innych ma możliwość zmiany loginu do konta. Co wtedy zrobisz?
- SELECT name,date FROM control JOIN users USING(id_user) Czyli podstawowe złączenie przy większej ilości rekordów będzie zwalniać gdyż porównywanie tekstów test kosztowne
Ad.2
Tego nie wiem
Ad. 3
Źle kombinujesz, ale radzę na początek nie zajmować się sposobem działania optymalizatora bazy danych. Wystarczy przyjąć, że sposób wyszukiwania zależy od konstrukcji pytania sql oraz indeksów, najszybsze są operacje na liczbach stałoprzecinkowych, a najwolniejsze jest porównywanie tekstów.
Ad. 6
Konstrukcja bazy ma być taka, że każde zapytanie sql będzie używać indeksu i nie będzie możliwe wpisanie danych powodujących niespójność bazy. Przykładowo zdefiniowanie klucza obcego id_user not null w tabeli control uniemożliwi dodanie rekordu do tej tabeli jeżeli w tabeli user nie będzie rekordu o odpowiednim id.
Nie da się też usunąć rekordu z tabeli users jeżeli będą rekordy o takim id w tabeli control.
W Twoim schemacie tabela companies nie jest powiązana z niczym, więc trudno mówić o indeksach i spójności.


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.