MySQL: система тегов

Предположим, у меня есть таблица, в которой может быть 0 или более тегов:

TABLE: foo
- foo_id (PK)

TABLE: tag
- tag_id (PK)
- name

TABLE: foo_tag
- foo_tag_id (PK)
- foo_id (FK)
- tag_id (FK)

Вопросы:

  1. Вышеупомянутый является наиболее распространенным и простым способом реализации системы тегов, который я видел. Я понимаю, что существуют потенциальные проблемы с системами тегов с точки зрения масштабируемости. Я собираюсь иметь это здесь?
  2. Есть ли способ сделать что-то подобное в PHP или SQL: вставить новый тег «bar». Если «полоса» не существует, добавьте ее в таблицу tag и верните последний вставленный идентификатор. Если «bar» действительно существует, не добавляйте его, а верните для него tag_id.
  3. Есть ли «правильный» термин БД для такой таблицы, описанной в №2?

person StackOverflowNewbie    schedule 27.11.2011    source источник
comment
Практически то же самое, что: stackoverflow.com/questions/20856/   -  person Kamil Lach    schedule 27.11.2011
comment
Ссылка, возможно, отвечает на вопрос №1. Для меня тоже важны вопросы №2 и №3.   -  person StackOverflowNewbie    schedule 27.11.2011


Ответы (3)


См. http://dev.mysql.com/doc/refman/4.1/en/insert-on-duplicate.html, чтобы узнать, как получить последний идентификатор при обновлении:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

Это обновит идентификатор последней вставки до значения обновленного значения. В твоем случае:

INSERT INTO tag (name) VALUES ('bar')
  ON DUPLICATE KEY UPDATE tag_id=LAST_INSERT_ID(tag_id);

tag.name должен быть уникальным ключом.

person hakre    schedule 27.11.2011
comment
tag.name будет УНИКАЛЬНЫМ. Если bar уже является записью и имеет tag_id, скажем, 10. Что возвращается при повторной попытке вставить bar? 10 ??? Это то, что я хочу. - person StackOverflowNewbie; 27.11.2011
comment
Да, 10, тогда LAST_INSERT_ID(tag_id) будет LAST_INSERT_ID(10), установив для последнего идентификатора вставки значение 10. Вызов mysqli_insert_id (или его эквивалента из C API last_insert_id()) вернет это значение 10. Просто проверьте это. Обратите внимание, что это специфично для MySQL. - person hakre; 27.11.2011

Если я что-то не пропустил, если ваша проблема с этой системой тегов - # 2 в вашем вопросе, который заключается в вставке нового тега «bar», если он не существует, попробуйте использовать INSERT IGNORE, вставка тега будет пропущена, если он существует, и я думаю, что это тот термин, который вы ищете в # 3 вот так:

INSERT IGNORE INTO Tag set name = 'bar';
person Mahmoud Gamal    schedule 27.11.2011
comment
Есть ли у меня проблемы с INSERT IGNORE? А для №3 я искал подходящий термин для обозначения таких таблиц. Например, я слышал, как люди называют foo_tag таблицей сопоставления. Ищу нечто подобное. - person StackOverflowNewbie; 27.11.2011
comment
Я думаю, что для его использования нет никаких проблем, просто посмотрите это: stackoverflow.com/questions/548541/, а также для №3. Если вы просто спрашиваете о соглашении об именах, я думаю, что это может быть так, как названо SO, просто Tags см. структуру Db на прямо на этой странице: data.stackexchange.com/stackoverflow/query/new. - person Mahmoud Gamal; 27.11.2011

# 2 Я бы установил уникальный ключ для tag.name. Предполагая, что у вас есть автоматическое увеличение tag_id, вы можете попробовать следующее:

function tagId($tag) {
  mysql_query("INSERT IGNORE INTO tag SET name='$tag'");
  if(mysql_affected_rows()) return mysql_insert_id();
  $result = mysql_query("SELECT tag_id FROM tag WHERE name='$tag'");
  if(!$result) return null;
  $data = mysql_fetch_row($result);
  if($data) return $data[0];
}
person Jan Turoň    schedule 27.11.2011