MYSQL בעיה.

  • פותח הנושא webi
  • פורסם בתאריך

webi

New member
MYSQL בעיה.

יש לי שדה שמוגדר כ VARCHAR ו BINARY . הבעיה עם השדה הזה שהוא רגיש להבדלים בין אותיות גדולות וקטנות באנגלית. למה? ומה אפשר לעשות כדי ש WEBI יהיה שווה ל webi ?
 

orenphp

New member
ברמת PHP

תנסה לעשות משהו כזה:
$q = "select * from table_name where field='" + strtolower($value) + "'";​
במידה וכל הטקסט שאצלך בטבלה נכתב באותיות קטנות זה יתן פתרון טוב. ניתן לעשות חיפוש לפי regualr expression בשאילתא ואז הוא לא יתייחס לאותיות גדולות/קטנות. אבל זה בד"כ יותר איטי.
 

webi

New member
אני משתמש ב MYSQL ב ASP

וביצעתי מעבר אליו מאקסס ששם לא היתה בעיה בנושא. היות שיש לי כבר מאות משתמשים אני לא יכול לשנות את זה. אני צריך פתרון ברמת ה SQL (אם יש) לצורך השוואה שמתעלמת בין אותיות גדולות וקטנות באנגלית...
 

webi

New member
פרוט נוסף:

לפי המדריך של MYSQL מסד זה הינו case-insensitive אבל בגלל שהגדרתי את שדות הטקסט שלי כ BINARY הוא הופך להיות case-sensitive , עיינו כאן: http://www.mysql.com/doc/en/Case_sensitivity.html הבעיה היא שאם לא הייתי מגדיר את שדות הטקסט כ BINARY ההשוואות של טקסט בעברית לא היו מתבצעות נכון (שאלתי פה כבר שאלה בעבר בנושא זה וזה מה שהומלץ לי וזה אכן פתר את בעיית השוואת טקסט בעברית) אבל עכשיו יש לי את הבעיה המנג'סת הזו עם אנגלית , מה לעשות???
 

orenphp

New member
אז אולי משהו כזה:

$q = "select * from table_name where LCASE('" + $value + "')";​
זאת פשוט פו' של mysql. http://www.mysql.com/doc/en/String_functions.html
 

webi

New member
הבעיה היא ש LCASE

תהפוך הכל לאותיות קטנות ומי ששם המשתמש או הסיסמה שלו כבר באותיות גדולות לא יוכל להכנס לאתר
אני די אובד עיצות בנושא. יש עוד רעיונות???
 

orenphp

New member
פיתרון לבעיה... או לפחות רעיון

קראתי קצת בmysql.com, ומה שאמרו שכדאי לעשות הוא כך: להגדיר את הטבלה שלך לא כBinary! כשאתה מחפש בעברית תוסיף Binary לשאילתא (אתה יכול לבדוק האם ה$value מכיל בתוכו אותיות עבריות באמצעות regular expression), במידה ואין מילים עבריות אז אל תוסיף דבר לשאילתא וכך יתבצע חיפוש שהוא case-insensitive הפיתרון מכיל בתוכו בעיה קטנה - על טבלאות גדולות החיפוש יהיה יותר איטי מאחר והאינדקסים לא מוגדרים כBinary. מקווה שזה עזר, אורן.
 

orenphp

New member
דוגמא למה שכתבתי.

הנה הקוד שדיברתי עליו (לא בדקתי, אבל זה העיקרון). רק במידה וישנן אותיות עבריות בקוד מתבצע חיפוש בינרי.
$add_binary_search = (preg_match("/[א-ת]/", $value)) ? "BINARY" : ""; $q = "Select * from table_name where $add_binary_search field='" + $value + "'";​
הבעיה היא שמה קורה ברגע שיש עברית ואנגלית עם אותיות קטנות וגדולות. זה כבר נהיה מסובך...
 

webi

New member
הבעיה עם הפתרון שלך

שיש לי משתמשים עם שמות משולבים בעברית ואנגלית ביחד... לדוגמא רוJית . עיין בתשובה שנתתי למטה לשנאור .
 

orenphp

New member
רעיון אחר...

תוכל לעשות משהו כזה: תכתוב שאילתא שתעבור על כל התוצאות שיש כרגע בטבלה ותשמור את הסיסמאות ואת שמות המשתמשים מחדש באמצעות הצפה מסוימת (למשל MD5) ככה בכלל לא יהיה אכפת לך מעברית, אנגלית, אותיות קטנות/גדולות וכו'. דוגמא:
//this code will convert all the existing usernames & passwords: $q = "select username, password, id from table_name"; while ($res = mysql_fetch_array(mysql_query($q)) { $upd_q = "update table_name set username = '" + md5($res["username"]) + "', password = '" + md5($res["password"]) + "' where id=" + $res["id"]; mysql_query($upd_q); }​
עכשיו שיש לנו הכל מוצפן בmd5 כל שעלייך לעשות בשביל לבדוק נכונות של משתמש:
$q = "select * from table_name where username = '" + md5($username) + "' and password = '" + md5($password) + "'"; echo (mysql_num_results(mysql_query($q)==1) ? "wellcome $username" : "invalid username or password"; //if we have more than one result, we have an error in the //registeration part - username & password must be unique.​
לא בדקתי את הקוד, אבל זה הרעיון. בהצלחה
 

webi

New member
תודה אני אבדוק את הפתרון

רק שאני צריך להמיר את הקוד שלך ל ASP
 

shanor

New member
מממ...

ההצעה של ORENPHP היא דרך טובה לפתור את זה. כמו שאמרת בעצמך, הומלץ לך להגדיר את השדה כבינארי כדי לפתור את הבעיתיות של העיברית. כך ה- MYSQL לא מנסה לעשות השוואות בין האותיות לבין עצמן (כפי שהוא היה עושה אם לא היה מוגדר בינארי, דבר שעובד כאשר מדובר באותיות לטיניות -בעיקר באנגלית) אלא עושה השוואה בין הערכים של האותיות. בעצם מה שקורה הוא שהשדה עצמו, בגלל ההגדרה של בינארי, מוגדר כשדה שיש לבדוק אותו לפי הערכים של התווים הנמצאים בו ולא לפי התווים עצמם. דבר זה פותר את בעיות הסידור של העיברית אבל יוצר בעיה כאשר רוצים להשתמש באותיות לטיניות גדולות וקטנות. ההצעה של ORENPHP הינה הצעה טובה ותעבוד, אבל כאן אתה מאבד את האותיות הגדולות והקטנות. אפשרות אחרת היא "להתחמק" מהבעיה על ידי הוספה של תווים מיוחדים אשר לא יופיעו על המסך אלא רק בתוך שדה הנתונים שלך... למשל נניח ובשדה שלך מותרים רק תווים רגילים משמע אותיות ומספרים ולא כל מיני סימנים נוספים... אז אפשר להחליט למשל שברמת ה- PHP תתבצע בדיקה של אותיות קטנות וגדולות ולפני כל אות גדולה ה- CHAR של ▲ (שהיא בסה"כ CHAR35, אבל אין לה משמעות על המסך - בדרך כלל). ולהכניס את המחרוזת החדשה באותיות קטנות עם ה-CHAR הנוסף לפני האותיות הגדולות. בעת השליפה, לבצע את אותו תהליך רק הפוך. לבדוק איפה נמצא ה-CHAR הזה ולהחליף אותו באות המקבילה הגדולה. עכשיו לבעיות, - פרט לקטע התיכנותי. - אם הסטרינג שלך ארוך, זה יכול ליצור האטה מסויימת בסקריפט שלך (- צריך לשים לב לזה). - הסטרינג שלך יגדל קצת (שוב צריך לשים לב שלמשל רק האותיות הראשונות הן גדולות ולא כל הסטרינג...). - יכול לעשות קצת בלגן בעת הסידור של כמה סטרינגים בינם לבין עצמם - כאשר הדבר ייעשה ברמת ה- MYSQL, אך גם על זה אפשר להתגבר ברמת ה-PHP. זהו בגדול, נראה לי שעברתי על הכל. בכל אופן, בהצלחה שנאור.
 

webi

New member
אני אגיד לך מה הבעיה שלי:

אם היום הייתי בונה את המסד מאפס ולא היו לי נתונים בו הייתי מכריח LCASE לכל מה שבאנגלית ונגמר הסיפור. הבעיה היא שיש לי כבר למעלה מ 1400 איש במסד הנתונים, חלק עם תווים מיוחדים, חלק בעברית, חלק באנגלית עם אותיות קטנות ,חלק באנגלית אותיות גדולות וחלק משולבות. לכן הבעיה.... אני מנסה להתמודד עם מצב נתון
 

shanor

New member
מממ...

קצת באיחור, אבל בכל זאת, נראה לי שאורן נתן כאן תשובה הולמת לבעיה שאתה מתאר. על פי מה שאתה מתאר, הכוונה היא לסיסמה ולא לשם המשתמש שהרי, לשם המשתמש אין משמשעות וחשיבות של אותיות גדולות וקטנות בעוד שלסיסמה יש משמעות. העברה של סיסמה לשאילתת MYSQL הצפנה של הסיסמה ב-MD5 והשוואה של הסיסמה המוצפנת למה שקיים במאגר היא תעבוד. הרי אין כאן עיניין של אותיות קטנות וגדולות עיברית ואנגלית - אין לזה משמעות כאן, הסיסמה של המשתמש והסיסמה במאגר חייבות להיות זהות 100%. מכאן אני ממשיך לדבר הבא, שם המשתמש. כמו שכתבתי קודם וכמו שאורן הציע, קח את שם המשתמש תעביר אותו לאותיות קטנות (בעזרת PHP למשל) ותבדוק האם יש לך את אותו שם משתמש במאגר שלך. מקסימום תבנה סקריפטון קטן (או שאילתה לא ממש מסובכת של UPDATE, שיעבירו את שמות המשתמש שלך לאותיות קטנות)... אני בשיטה הזו אולי אפילו הייתי בודק האם אפשר בכלל לוותר על כל הבינארי לחלוטין. תעשה ניסוי קטן, תגדיר שם משתמש בעיברית, כאשר השדה לא מוגדר כבינרי, ותבדוק אם אתה מצליח להתחבר בעזרתו. לדעתי לא אמורה להיות בעיה (חשוב שתשתמש בממשק זהה בעת הכנסת שם המשתמש החדש והבדיקה שלו בשביל ENCODING ו-CHARACTERSET זהים). עכשיו בוא נחזור למשהו שכתבת בהתחלה... רצית להשוות שדות עם תווים בעיברית אז הגדרת אותם כבינרי, למה אתה צריך את זה כאן? מסורבל קצת אני יודע, אבל לדעתי שווה לנסות. מקווה שהייתי ברור מספיק. בהצלחה שנאור.
 

webi

New member
איך פתרתי בסוף את הבעיה:

האמת ממש ממש פשוט. כל משתמש חדש שנרשם לאתר כמובן אוט' מבוצע עליו LCASE ואז לא משנה אם הוא מכניס אנגלית באותיות גדולות אני מטפל בו. לגבי הקיימים הרצתי עליהם שאילתא שהופכת את כולם לאותיות קטנות והודעתי שיש להשתמש באנגלית רק באותיות קטנות ונסגר הסיפור..... על הבינארי אי אפשר לוותר (לצערי) כי השוואות בעברית יצאו על הפנים!!! הכי מדהים היה שבקשה של משתמשת בשם תותי הביאה (למרבה הפלא) משתמשת בשם שושי, למה ? לחוסר הבינארי פתרונים...
 

orenphp

New member
אפשר לינק לאתר?

לבדוק אותך טיפה. אני מעוניין לראות אם חשבת על כל הדברים. אני טיפה סקפטי, מצטער, אני לא מתכוון לזלזל אבל נראה שלא חשבת עד הסוף בעניין. התנצלותי מראש במידה ואני לא ימצא כלום :)
 
למעלה