[mysql] Porownywanie z uzyciem LIKE

0

Witam,

mam taka tabelke:

CREATE TABLE Source_Destination_Route
   (sd_route_no INT,
    flight_arr VARCHAR(20),
    flight_dep VARCHAR(20),
    CONSTRAINT pk_SDRoute PRIMARY KEY(sd_route_no)) ENGINE=InnoDB;

tutaj insert:

 insert into Source_Destination_Route values (1, "Lillby", "Smallville");
insert into Source_Destination_Route values (2, "Smallville", "Lillby");

i napisalem procedure:

DROP PROCEDURE IF EXISTS `porownanie` ;
delimiter //

CREATE PROCEDURE porownanie (nazwa VARCHAR(20))
BEGIN CREATE TEMPORARY TABLE TempTable (
   sd_route_no INT
);
  
INSERT INTO TempTable (sd_route_no)
select sd_route_no
from Source_Destination_Route 
WHERE flight_dep LIKE '%nazwa%';
SELECT * FROM TempTable; DROP TABLE TempTable;
END;
//
delimiter ;

CALL porownanie('Lillby');

czy ktos jest w stanie powiedziec mi dlaczego ona nic nie zwraca?

0

'%nazwa%' zamień na '%' + nazwa + '%' i pomyśl dlaczego tak :/

0

dlatego: WHERE flight_dep LIKE '%nazwa%';

ani "Smallville", ani "Lillby" nie zawiera ciagu znakow 'nazwa'

a do parametrow nie nie tak odwoluje

// eh decydujace sekundy mnie pograzyly :)

0
Misiekd napisał(a)

'%nazwa%' zamień na '%' + nazwa + '%' i pomyśl dlaczego tak :/

cos nie bardzo, bo sie mysql o te plusy chyba rzuca ;/

0

'%' || nazwa || '%'
a najlepiej sobie poszukaj w dokumentacji

0
Misiekd napisał(a)

'%' || nazwa || '%'
a najlepiej sobie poszukaj w dokumentacji

przepraszam, ze tak drecze, ale dawno nie uzywalem mySqla. Mam blad, probowalem szukac jakiegos rozwiazania, ale nie znalazlem nic konkretnego:

ERROR 1292 (22007): Truncated incorrect INTEGER value: '%'

Ogolnie procedura sie laduje, dopiero przy wywolaniu pokazuje sie ten blad.

0

dobra MySQL to dziwna baza :/

WHERE flight_dep LIKE concat('%', nazwa, '%');

0

dzieki, dziala! :) uratowales mi zycie :)

0

chcialem jeszcze jedno pytanie, zeby nie zakladac nowego tematu.

Mam 3 tabele:

CREATE TABLE Passenger
   (passenger_no VARCHAR(50),
    f_name VARCHAR(10),
    l_name VARCHAR(20),
    age INT,
    gender ENUM('M','F'),
    CONSTRAINT pk_Passenger PRIMARY KEY(passenger_no)) ENGINE=InnoDB;

CREATE TABLE Booking
   (id INT NOT NULL AUTO_INCREMENT,
    seat_reserved INT,
    date DATE,
    booking_price INT,
    booking_status ENUM('Confirmed','Not confirmed') DEFAULT 'Not confirmed',
    booking_no VARCHAR(50),
    phone_number INT,
    email VARCHAR(20),
    age_category ENUM('A','Y','I'),
    flight INT,
    passenger VARCHAR(50),
    payment VARCHAR(50),
    CONSTRAINT pk_Booking PRIMARY KEY(id)) ENGINE=InnoDB;

CREATE TABLE Payments
    (payment_no VARCHAR(50),
    amount INT,
    card_expiry_month INT,
    card_expiry_year INT,
    card_no INT,
    card_holder VARCHAR(20),
    date DATE,
    CONSTRAINT pk_Payments PRIMARY KEY(id)) ENGINE=InnoDB;

do wypelnienia Booking i Passenger uzywam procedury:

DROP PROCEDURE IF EXISTS add_booking;
delimiter //

CREATE PROCEDURE add_booking
(IN p_f_name VARCHAR(10), IN  p_l_name VARCHAR(20), IN  p_age INT, IN p_gender ENUM('M','F'),
 IN p_seat_reserved INT, IN p_date DATE, IN p_phone_number INT, IN p_email VARCHAR(20), IN p_age_category ENUM('A','Y','I'), IN p_flight INT)
BEGIN
 Declare Code varchar(50);
                      
         SELECT UUID() into Code;     
   
      Insert into Passenger (passenger_no, f_name, l_name, age, gender)
      Values
      (
         Code, p_f_name,  p_l_name, p_age, p_gender
      );

	
      Insert into Booking (seat_reserved, date, phone_number, email, age_category, flight, passenger)
      Values      
     (
        p_seat_reserved, p_date, p_phone_number, p_email, p_age_category, p_flight, Code
     );
  

END;
//
delimiter ;

a do Payment takiej:

DROP PROCEDURE IF EXISTS `add_payments` ;

delimiter //
CREATE PROCEDURE add_payments
     (
        nazwisko VARCHAR(20), p_card_expiry_month INT,p_card_expiry_year INT,p_card_no INT,p_card_holder VARCHAR(20),p_date DATE
     )
BEGIN  

INSERT INTO Payments (card_expiry_month,card_expiry_year,card_no,card_holder,date)
VALUES (p_card_expiry_month,p_card_expiry_year,p_card_no,p_card_holder,p_date); 

UPDATE Booking b, Payments s,Passenger p
SET payment_no = passenger_no
where p.l_name LIKE concat(nazwisko, '%');
END;
//

delimiter ;

Chodzi mi o to, zeby tabele Passenger i Payment mialy taki sam numer w passenger_no i payment_no. Chcialem sprawdzic jaki numer ma osoba o nazwisku podanym jako parametr i przypisanie, i to dziala, ale tylko za pierwszym razem, bo pozniej pisze ze zdublowalem klucz. W jaki sposob moge zmodyfikowac tego UPDATE'a ?

Bede bardzo wdzieczny za pomoc.

0

zaczne od slowa: masakra
teraz uzasadnienie

wiesz ze na swiecie jest wiecej niz jeden Kowalski?
jesli zdajesz sobie z tego sprawe to natychmiast zadepcz add_payments

po pierwsze aby poprawnie polaczyc platnosc z rezerwacja (ktora jest powiazana z klientem) musisz miec jakis unikatowy identyfikator, na podstawie, ktorego jednoznacznie stwierdzisz jakiej rezerwacji dotyczy platnosc - idealnie byloby miec Booking.id (a nie nazwisko)

nie widze pola id w tabeli Payments
czy przypadkiem w tej tabeli PK nie jest pole payment_no? jesli tak to kazdy klient moze zrobic tylko jedna platnosc, ever!!! :)

na poczatek nalezaloby troche ladu wprowadzic do tabelek i relacji miedzy nimi, a pozniej napisac odpowiednia logike

0
massther napisał(a)

zaczne od slowa: masakra
teraz uzasadnienie

wiesz ze na swiecie jest wiecej niz jeden Kowalski?
jesli zdajesz sobie z tego sprawe to natychmiast zadepcz add_payments

po pierwsze aby poprawnie polaczyc platnosc z rezerwacja (ktora jest powiazana z klientem) musisz miec jakis unikatowy identyfikator, na podstawie, ktorego jednoznacznie stwierdzisz jakiej rezerwacji dotyczy platnosc - idealnie byloby miec Booking.id (a nie nazwisko)

nie widze pola id w tabeli Payments
czy przypadkiem w tej tabeli PK nie jest pole payment_no? jesli tak to kazdy klient moze zrobic tylko jedna platnosc, ever!!! :)

na poczatek nalezaloby troche ladu wprowadzic do tabelek i relacji miedzy nimi, a pozniej napisac odpowiednia logike

:D na swoje usprawiedliwienie moge dodac, ze tyle razy modyfikowalem te tabelki, ze glowa mala. Pole id w Payments juz mialem, ale usunalem jak sie bawilem z tym i zapomnialem znowu dopisac :) Co do wyszukiwania po nazwisku, to tez pozostalosc po tych zmianach, bo ogolnie to mialo byc na probe, na kontrolowanej ilosci rekordow, w pozniejszej wersji chcialem wyszukiwac po tym unikalnym kluczu.

A jesli juz o kluczach mowa, to uzywam sobie tego UUID(), ale to zwraca dlugi ciag znakow, a ja potrzebuje jedynie tych pierwszych 8, gdzie sa roznice. Da sie jakos w latwy sposob to zrobic ?

Chcialem moze jeszcze wyjasnic o co tak na prawde mi chodzi z tym add_payments. Mianowicie dodajac osoby poprzez add_booking, sa one ladowane do tabel po kolei. Ale przeciez do payments osoby nie musza podawac informacji w takiej kolejnosci jak maja numer w tabeli Passenger. I tu jest moj problem - w jaki sposob polaczyc odpowiednio te 2 tabele, zeby Kowalski nie zaplacil za Nowaka.

0

jesli chodzi o uuid proponuje pozostac przy tej wartosci, ktora jest zwracana, bo jest to standard zapewniajacy niepowtarzalnosc generowanych identyfikatorow, inaczej musialbys sam napisac jakis generator, ale to masa roboty
wieksosc jezykow programowania ma specjalne typy do obslugi uuid (w microsofcie i sql serverze guid)
poza tym uuid maja zazwyczja 36 znakow, dokladnie, wiec proponuje passenger_no zrobic jako char(36)

przyjmujac platnosc, powinienes zrobic to przez taki mechanizm, aby moc jednoznacznie zidentyfikowac jakiej rezerwacji tyczy sie platnosc
opisze na przykladzie serwisu internetowego
klientowi robiacemu rezerwacje generujesz odpowiedni link do strony platnosci z odpowiednim query stringiem, czyli np. z userId i bookingId, dzieki tym dwom identyfikatorom mozesz sprzwdzic czy dany booking jest dla danego usera, jesli sie zgadza, to przyjmujesz platnosc i dokladnie wiesz ze jest ona dla bookingId
oczywiscie profesjonalnie zrobiony serwis jawnie nie powinien wyslac w query str. tych identyfikatorow, zazwyczaj generuje sie jakis uuid dla kombinacji userId, bookingId
mozna jeszcze strorzyc jakis hash z pewnych danych dotyczacych rezerwacji i takze dolaczyc do qs i przy wejsciu na strone sprawdzic jego poprawnosc

0
massther napisał(a)

jesli chodzi o uuid proponuje pozostac przy tej wartosci, ktora jest zwracana, bo jest to standard zapewniajacy niepowtarzalnosc generowanych identyfikatorow, inaczej musialbys sam napisac jakis generator, ale to masa roboty
wieksosc jezykow programowania ma specjalne typy do obslugi uuid (w microsofcie i sql serverze guid)
poza tym uuid maja zazwyczja 36 znakow, dokladnie, wiec proponuje passenger_no zrobic jako char(36)

przyjmujac platnosc, powinienes zrobic to przez taki mechanizm, aby moc jednoznacznie zidentyfikowac jakiej rezerwacji tyczy sie platnosc
opisze na przykladzie serwisu internetowego
klientowi robiacemu rezerwacje generujesz odpowiedni link do strony platnosci z odpowiednim query stringiem, czyli np. z userId i bookingId, dzieki tym dwom identyfikatorom mozesz sprzwdzic czy dany booking jest dla danego usera, jesli sie zgadza, to przyjmujesz platnosc i dokladnie wiesz ze jest ona dla bookingId
oczywiscie profesjonalnie zrobiony serwis jawnie nie powinien wyslac w query str. tych identyfikatorow, zazwyczaj generuje sie jakis uuid dla kombinacji userId, bookingId
mozna jeszcze strorzyc jakis hash z pewnych danych dotyczacych rezerwacji i takze dolaczyc do qs i przy wejsciu na strone sprawdzic jego poprawnosc

Nie wiem czy dobrze zrozumialem, ale sprobuje przedstawic Ci co ja chcialem zrobic i powiesz czy to bardzo glupie.
Mianowicie generujac UUID dla tabeli Passenger(passenger_no) zapisuje go rownoczesnie do tabeli Booking(passenger). Nastepnie w procedurze payment chcialem podac passenger_no i wtedy sprawdzic w ktorym wierszu w tabeli Booking wystepuje ten sam ciag znakow. Jak dopasuje, to wtedy do tabeli Booking(payments) dodac numer id z tabeli Payments. Ale nie wiem czy to ma jakis sens i czy da sie to w prosty sposob zrobic, a nawet jesli sie da, to przeciez nie bede przy kazdym wywolaniu przepisywal 36 znakow, bo to troche duzo.

Chcialbym miec najprostsza mozliwa procedure, ale nie wiem jak sie za to zabrac, to frustrujace.

0

ja bym proponował abyś wziął to co masz i to olał :). Aby to działało chociaż tak aby można było powiedzieć, że działa. Jeśli robisz to na jakieś zaliczenie to profesor/nauczyciel/whatever zaraz Ci wytknie dokładnie te same problemy co massther.

Zaczynając od początku

  1. każda tabela powinna (czasami są uzasadnione przypadki, że nie musi) mieć klucz główny. Klucz główny ma to do siebie, że NIGDY nie może się powtórzyć. Takie dane jak nazwisko, pesel, adres itp NIE NADAJĄ się na PK.
  2. Klucz główny, z racji iż jest często używany do wyszukiwania (np. przy złączeniach) powinien być jak najbardziej upakowany (jak najwięcej możliwych kombinacji na jak najmniejszej ilości bitów) i łatwy do porównywania. UUID nie spełnia żadnych z tych założeń. kolumna char(32) jako klucz główny średnio się nadaje. Zazwyczaj PK są pola typu int lub AUTO_INCREMENT jeśli baza takowe wspiera. W szczególnych przypadkach (często przy tabelach słownikowych) są to pola znakowe, ale o długości kilku znaków a nie 32.
  3. moja propozycja
Passenger
-------------
* passenger_id INT NOT NULL AUTO_INCREMENT
   f_name VARCHAR(10)
   l_name VARCHAR(20)
   age INT
   gender ENUM('M','F')
Booking
-------------
* booking_id INT NOT NULL AUTO_INCREMENT
   seat_reserved INT
   date DATE
   booking_price numeric(10,2) <-cena nie może być liczbą całkowitą, chyba, że przyjmiesz, że cena jest w groszach a nie w pln
   booking_status ENUM('Confirmed','Not confirmed') DEFAULT 'Not confirmed'
   phone_number VARCHAR(15) <- telefon powinien być jako string - a jak ktoś poda nr z myślnikami albo spacjami
   email VARCHAR(20)
   age_category ENUM('A','Y','I')
   flight INT
Passenger_Booking <-nie wiem jak to inaczej nazwać :)
-------------
# passenger_id INT 
# booking_id INT
Payments
-------------
*  payment_id INT NOT NULL AUTO_INCREMENT
   amount numeric(10,2)
   card_expiry_month INT
   card_expiry_year INT
   card_no INT
   card_holder VARCHAR(20)
   date DATE
#  booking_id INT 

Legenda:

PK</li> </ul> </li> </ul> FK </li> </ul> </li> </ol>

Parę słów wyjaśnienia

  1. pasażer jest pasażer :) nie ważne ile ma rezerwacji, na jakie loty i na kiedy. Jeśli jest to ta sama osoba to powinna mieć tylko JEDEN rekord z danymi i tylko jedno swoje własne unikalne id.
  2. jeden pasażer może mieć wiele rezerwacji
  3. na jednej rezerwacji może być zarejestrowanych kilku pasażerów - stąd tabelka Passenger_Booking
  4. do jednej rezerwacji może być kilka płatności - np. 10% w przeciągu 24h od rezerwacji a reszta 24h przed odlotem lub na miejscu. Ważne, że do jednej rezerwacji może być wiele płatności

Co do funkcji to proponuję takie (każda (oprócz add_passenger_booking) zwracająca ID dodanego rekordu)
add_passenger(dane pasażera)
add_booking(dane rezerwacji)
add_payments(booking_id, dane płatności)
add_passenger_booking(booking_id, passanger_id)

0

Dzieki bardzo Misiekd, ze chcialo Ci sie w nocy napisac cos tak dlugiego:) i Massther'owi tez dziekuje :)
Zastosowalem sie do Twoich rad i pozmienialem to wszystko, i teraz smiga, i w ogole.

1 użytkowników online, w tym zalogowanych: 0, gości: 1