Mysql вывести отношение внешнего ключа для случайных запросов - PullRequest
2 голосов
/ 29 декабря 2011

Я новичок в MySQL и ищу решение следующей проблемы:

Я хотел бы создать CMS с cppcms, которая будет иметь возможность иметь модули. Поскольку я хочу уменьшить вероятность (случайного) доступа к частным данным, я хочу модуль, который обрабатывает доступ к данным и права. Поскольку предполагается, что этот модуль не знает о структурах данных, созданных другими модулями, я бы хотел, чтобы он выводил владельца данных через отношения внешний ключ . Моя идея заключается в поиске пути (по внешним ключам), который связывает строку с идентификатором пользователя.

Подводя итог: Что я пытаюсь сделать

  1. Принимая случайный запрос, определите затронутые строки
  2. для затронутых строк определить отношение / путь (через внешние ключи) к пользователю / идентификатору пользователя (столбец в существующей таблице)
  3. возвращает только те строки, для которых может быть определена связь и выполняется условие (например, идентификатор пользователя, найденный в связанном запросе, соответствует фиксированному идентификатору пользователя, например, пользователю, который в данный момент обращается к системе)

(Насколько мне известно, внешние ключи только обеспечивают существование ключа в другой таблице, однако я предполагаю предварительное условие, что каждая строка связана с пользователем по пути отношений внешнего ключа)

Моя проблема / вопрос:

  1. Существует ли существующее решение / лучший подход к проблеме? Подготовленные операторы не помогут, так как я заранее не знаю всех структур данных / запросов.

  2. Как мне получить отношения по ключевым словам? Есть ли другой способ, кроме «SHOW CREATE TABLE» и последующего анализа строки результата?

  3. Как определить строки, которые будут затронуты, без их изменения? Я хотел бы отфильтровать этот набор впоследствии, определив, могу ли я связать его с текущим пользователем (не пользователем mysql, а системным пользователем).

Могу ли я попытаться выполнить запрос, а затем выбрать соответствующие строки, и если я определю нарушение доступа, просто сделайте откат? Проблема с этим: как сделать изменения в подмножестве строк, для которых это допустимо (например, я пытаюсь изменить 5 строк, может изменить только 2, как изменить только эти 2). Одна идея состояла в том, чтобы найти способ создать временную таблицу с набором результатов; у этого решения есть несколько недостатков: отношения внешних ключей невозможны для временных таблиц, они «потеряны».

P.S .: Я пишу код на c ++, поэтому я бы предпочел рекомендации cpp-совместимой библиотеки, однако я открыт для других предложений. Погугливая, я наткнулся на доктрину, и в настоящее время Я исследую ее. P.P.S .: Движком базы данных является InnoDB (должен из-за внешних ключей)

ОБНОВЛЕНИЕ: Объяснение Попытка части 2: Я пытаюсь отфильтровать столбцы, которые пользователь может видеть в таблицах. Для этого я хотел бы найти соединение в базе данных по внешним ключам (по внешним ключам я гарантирую, что могу получить доступ ко всем данным через объединения, и они являются подсказкой, к каким столбцам я должен присоединиться). Поскольку я планирую использовать более сложную систему (например, форум), я не хочу объединять все данные во временную таблицу и выполнять пользовательский запрос по ним. Я бы предпочел оценить пользовательский запрос и проверить результат, если я могу сопоставить его с объединением с идентификатором пользователя. Например, я мог бы использовать это для принудительного включения кнопки редактирования только для сообщений, созданных пользователем. (Я знаю, что есть более простые способы сделать это, но я в основном хочу позволить программистам писать свои собственные запросы, не давая им возможности редактировать или просматривать данные, которые им не разрешено видеть. Я предполагаю, что программист не зло, но я просто забываю ограничения, поэтому я хочу применить их в программном обеспечении).

Было бы неплохо добраться сюда, но мне нужно немного более сложное.

Сначала базовый пример. Допустим, это как Facebook, и все друзья человека могут видеть его фотографии.

pictures = id **userid** file (bool)visibleForFriends album
friendship = **userid1** **userid2**
users = userid

То, что я хочу, это:

  1. Программный ввод "SELECT * FROM pictures WHERE album = 2"
  2. Система получает все соответствующие записи (например, набор идентификаторов)
  3. Система видит идентификатор пользователя внешнего ключа, пытается сопоставить текущий идентификатор пользователя сидентификатор изображения, добавляет все совпадения к возвращенной части результата
  4. Системные уведомления специальный столбец visibleForFriends
  5. Система пытается определить всех друзей (ВЫБРАТЬ userid1 ИЗ дружбы, ГДЕ userid2 = currentUserIDобъединение (необходимо прочитать об объединениях) ВЫБРАТЬ userid2 ИЗ дружбы, ГДЕ userid1 = currentUserID)
  6. Система добавляет все строки, где visibleForFriends равно true и pictures.userid = Результат из 5.

Хотя часть Friendship - это некоторый дополнительный код (я думаю выполнимо, если igot запускается с первого бита), мне все еще нужно выяснить, как автоматически следовать внешним ключам, чтобы увидеть соединение.Не обращая внимания на особый случай дружбы (особый случай), я бы хотел, чтобы система работала и над этим:

pictures = id **albumid** file (bool)visibleForFriends album
albums = id **userid**
users = userid

Теперь система должна отправлять фотографии. albumid ==> альбомы.id -> album. userid ==> users.userid.

Надеюсь, примеры немного прояснили вопрос.Одна проблема заключается в том, что в первом пункте примера (ввод запроса программистом) я не хочу, чтобы «УДАЛИТЬ *» вступало в силу для всего, что не принадлежит пользователю.Поэтому мне нужно отфильтровать строки, которые нужно удалить.

Ответы [ 2 ]

1 голос
/ 29 декабря 2011

В ответ на часть вашего ответа (часть 1), предоставив пользователю Mysql, к которому вы обращаетесь к базе данных, права доступа к information_schema, вы можете использовать следующий запрос, чтобы понять существующие связи внешних ключей в конкретной базе данных:

SELECT 
    TABLE_NAME,
    COLUMN_NAME,
    REFERENCED_TABLE_NAME,
    REFERENCED_COLUMN_NAME
FROM
    information_schema.KEY_COLUMN_USAGE
WHERE
    TABLE_SCHEMA = 'dbname' AND REFERENCED_COLUMN_NAME IS NOT NULL;

Меня немного смущает часть 2, и я не уверен, как дать соответствующий ответ на этот раздел. Я надеюсь, что вы найдете этот запрос полезным в вашем проекте!

0 голосов
/ 03 января 2012

Существует ли существующее решение / лучший подход к проблеме?

Да, я так думаю.Вы описываете многопользовательскую базу данных.В многопользовательской базе данных, в которой пользователи совместно используют таблицы (также известные как «все разделенные»), в каждой таблице должен быть столбец для идентификатора пользователя.По сути, каждая строка знает своего владельца.

Это значительно упростит ваш SQL, так как вам не нужны объединения, чтобы определить, кому принадлежит строка.это, вероятно, также значительно ускорит ваш SQL.

Этот ответ SO содержит краткое изложение проблем и альтернатив.

...