|
Тема
|
MySql въпрос
|
|
Автор |
edembg (Ученик) |
Публикувано | 20.02.04 09:18 |
|
Здравейте.
Имам следният проблем:
Имам примена таблица в MySql с полета ID int auto_increment, user char, a int, b int.
Често ми се налага да проверявам дали има запис за user = "abc", а = 0, b = 0.
Ако няма трябва да го създам и да взема ID.
За да направя това правя четири заявки. Не мога да измисля начин това да става по-икономично.
Моля, ако някой знае как и има желание, да помогне.
Благодаря
И най-ярките личности си плащат тока.
| |
Тема
|
Re: MySql въпрос
[re: edembg]
|
|
Автор |
unF (.)(.) |
Публикувано | 20.02.04 11:14 |
|
<?
$q = "SELECT * FROM tableName WHERE user = 'abc' AND a = '0' AND b = '0'";
$r = mysql_fetch_object(mysql_db_query($dbname,$q,$dblink));
if ($r->id != 0){
$id = $r->id;
}else {
$q = "INSERT INTO tableName SET user = 'abc', a = '0', b = '0'";
$r = mysql_db_query($dbname,$q,$dblink);
$id = mysql_insert_id();
}
?>
ako pravilno sym te razbral taka shte stane s nai-mnogo dve .. :)
unF ..
| |
Тема
|
Re: MySql въпрос
[re: edembg]
|
|
Автор |
salle (един такъв) |
Публикувано | 20.02.04 12:38 |
|
"Ако няма трябва да го създам и да взема ID"
А ако го има какво правиш? Пак ли ти трябва ID?
В най-лошия случай ти трябват 3 заявки. За какво са ти 4?
Втори въпрос - това, което описваш означава ли, че user,a,b е уникална комбинация? Ако да добави един UNIQUE ключ. Предпалага се, че ID вече ти е Първичен (PRIMARY KEY)
Ако те интересува ID само в случай, че вмъкваш нов запис тогава просто правиш INSERT и проверяваш за грешка. Уникалния ключ ще се погрижи да ти върне грешката. Ако няма грешка взимаш SELECT LAST_INSERT_ID() и готово - 1 или 2 заявки.
Допълнителна разлика е че така гарантираш, че няма да се появят два еднакви реда. Иначе трябва да заключваш таблицата преди цялата последователност и да я отключваш после
Ако ID винаги те интересува, което е доста по-логичния вариант пак минаваш с 1 или 3 заявки
SELECT ID FROM tbl WHERE user = "abc" AND а = 0 AND b = 0';
Ако върне ID си готов - 1 заявка.
Ако върне празен резултат
INSERT INTO tbl (user, a, b) VALUES('abc', 0, 0);
SELECT LAST_INSERT_ID();'
3 заявки
| |
Тема
|
Re: MySql въпрос
[re: unF]
|
|
Автор |
edembg (Ученик) |
Публикувано | 20.02.04 16:29 |
|
Мноиго благодаря. Така е доста по-добре.
И най-ярките личности си плащат тока.
| |
Тема
|
Re: MySql въпрос
[re: salle]
|
|
Автор |
edembg (Ученик) |
Публикувано | 20.02.04 16:50 |
|
Благодаря. Нещо подобно правя и аз, но по-дървено.
И най-ярките личности си плащат тока.
| |
Тема
|
Re: MySql въпрос
[re: salle]
|
|
Автор |
unF (.)(.) |
Публикувано | 20.02.04 22:36 |
|
Амм .. аз не разбрах в моя отговор има ли някаква грешка и ако има каква е защото и на мен ми се налага много често да ползвам подобно нещо и ако има ще е хубаво да разбера ;)
unF ..
| |
Тема
|
Re: MySql въпрос
[re: unF]
|
|
Автор |
edembg (Ученик) |
Публикувано | 22.02.04 10:26 |
|
Според мен и двата примера са идентични. Sale не предполага, че се прави нещото на PHP и за това го обяснява малко по-различно.
Аз губех една заявка само за проверка за съществуването на съответният запис. За това при мен бяха четири заявки.
Изпробвах всички варианти и всичко си работи.
И най-ярките личности си плащат тока.
| |
Тема
|
Re: честно казано ...
[re: unF]
|
|
Автор |
salle (един такъв) |
Публикувано | 22.02.04 18:29 |
|
.. не точно грешка, но имам някои много сериозни забележки към твоя отговор.
Първото е, че човекът не пита за PHP - може примерно от Java да работи или през ODBC и т.н.
Но това да кажем е малък проблем - дал си пример като за PHP
Само, че в твоя отговор има някои много сериозни логически грешки. Ти може и да си ги знаеш, но не е хубаво да даваш такива съвети. Тези които те четат обикновено повтарят едно към едно (направо Copy/Paste) а значи повтарят и грешките ти.
$q = "SELECT * FROM tableName WHERE user = 'abc' AND a = '0' AND b = '0'";
$r = mysql_fetch_object(mysql_db_query($dbname,$q,$dblink));
if ($r->id != 0){
Правиш SELECT * ... когато реално ти трябва само ID
Това е грубо разхищение на ресурси както и да го погледнеш. Само една такава разлика между SELECT * FROM и SELECT ID FROM може да ти забави стотици пъти приложението и да ти изяде огромно количество памет съвсем ненужно.
Това е основно правило не само в базите данни но и изобщо в програмирането. Никога не изисквай нещо което няма да използваш. Независимо дали става въпрос за данни, памет и т.н.
Следващото нещо за което вече си за бой (виртуален )
$r = mysql_fetch_object(mysql_db_query($dbname,$q,$dblink));
if ($r->id != 0){
Викаш mysql_query без да провериш резултата за грешка. Никога не бива да го правиш ама в случая дори не става въпрос за теб.
Даваш съвет на някой друг! Не бива да забравяш, че тези които четат твоя съвет може и нищичко да не разбират. И след това ще идват тук и нявсякъде другаде да питат защо гърми еди как си.
Никак не е случайно, че и най-най-най-простичките примери на php.net изгреждат ето така:
Example 2. mysql_query()
<?php
$result = mysql_query("SELECT my_col FROM my_tbl")
or die("Invalid query: " . mysql_error());
?>
И накрая нещо, което може просто да не знаеш
$q = "SELECT * FROM tableName WHERE user = 'abc' AND a = '0' AND
$q = "INSERT INTO tableName SET user = 'abc', a = '0', b = '0'";
$id = mysql_insert_id();
ako pravilno sym te razbral taka shte stane s nai-mnogo dve .. :)
Това са три заявки а не две
mysql_insert_id();
просто изпраща към сървъра
SELECT LAST_INSERT_ID();
Надявам се да не се разсърдиш иска ми се съветите ми са приятелски.
Колкото до задачката като такава тя наистина е много често срещана, но силно зависи от конкретната структура на таблицата.
Кое е първичния ключ?
Има ли втори уникален ключ или не?
Всички стойности ли се задават в INSERT или някои се оставят по подразбиране?
Има ли AUTO_INCREMENT?
Какво се прави в случай на съществуващ запис? Просто продължаваш нататък или правиш UPDATE на съществуващия?
Има ли проблем с конкурентността? При PHP в 99% от случаите има - може много браузъри едновременно да отворят този скрипт.
С транзакции ли се работи или не?
Има и още подробности. Ако искате може да поразвием темата в различни варианти.
В някои случаи може да се мине с една заявка:
REPLACE INTO
или един синтаксис който го има от 4.1 нагоре
INSERT INTO .... ON DUPLICATE KEY UPDATE ....
в други случаи може да трябват 4 заявки
LOCK ...
SELECT ...
INSERT ...
UNLOCK ...
| |
Тема
|
Re: честно казано ...
[re: salle]
|
|
Автор |
edembg (Ученик) |
Публикувано | 23.02.04 19:47 |
|
За всичко си прав. Не се бях замислял толкова дълбоко за проблема. Но в резултат на вашите съвети, тази част от моят PHP скрипт стана така:
<?
$query = 'select order_id from '._tbl_order.' where user_id = "'.session_id().'" && payed = 0 && costum = 0';
$result = $this->db->dbquery($query);
$row = $this->db->fetch_array($result);
$this->db->free_result($result);
if (!$row)
{
if (isset($GLOBALS['_REQUEST']['order']))
{
$query = 'insert into '._tbl_order.' set indate = '.time().', user_id = "'.session_id().'"';
$this->db->dbquery($query);
$this->order_id = $this->db->insert_id();
} else return ;
} else $this->order_id = $row['order_id'];
?>
MySql функциите викам през отделен клас. Мисля, че отговаря на препоръките ти.
Ако нещо не е добре, критикувай спокойно. Така е по-добре от похвали на лоши неща.
Благодаря още веднаж.
И най-ярките личности си плащат тока.
| |
|
|
|
|