2017-01-14 3 views
0

На текущем сервере MySQL MySql у меня есть две схемы: «Друзья», «Места». Вся БД организована вокруг хранимых процедур, вызываемых извне. Может быть, это хороший подход, может быть, это плохо, но это не связано с этой проблемой, которую я испытываю. В этом случае DB необходимо отделить от любого внешнего программного обеспечения, используя его (поскольку я только отвечаю за БД).Динамические альтернативы SQL (MySql)

Некоторые хранимые процедуры из схемы «Друзья» относятся к таблицам из «Места» и наоборот. Теперь, если, например, я хочу установки нового набора схем, на том же сервере, но для другого «клиента», как это:

Friends_clientOne 
Places_clientOne 
Friends_clientTwo 
Places_clientTwo 

У меня проблема - хранимые процедуры, относящиеся таблицы из другой схемы воны» t знать, какое имя схемы использовать. Проверка и изменение каждой процедуры для каждого подходящего имени схемы при каждом создании нового набора не является вариантом. Динамический SQL для меня совершенно новый - какие другие варианты? Как я, например, сделать это:

(stored procedure inside schema Friends_clientOne): 
Select * from Places_<getCurrentSchemaSuffix>.someTable; 

Скажите, пожалуйста, MySql является достаточно гибким для этого :(Что о Percona

+0

Параметр 'SQL-server' теги, связанные с Microsoft SQL Server и не имеет никакого отношения к делать с MySQL. – tadman

+0

Этот вид проблемы является симптомом плохого дизайна – Strawberry

+0

Это MySql, отредактированный – guest86

ответ

2

ближе всего к то, что вы описываете, является встроенная функция DATABASE()? (http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_database), которая возвращает текущую по умолчанию базы данных.

база данных по умолчанию не обязательно один, что данная таблица принадлежит. это база данных совсем недавно названный в USE <databasename> заявлении. Если вы можете положиться на приложение всегда использует d atabase, который вы имеете в виду для этой таблицы, которой вы принадлежите, тогда вы можете использовать эту функцию.

Однако реализация SQL не позволяет динамически изменять имя таблицы во время выполнения запроса. Таблицы можно назвать только до, делая подготовку инструкции и жестко кодируя ее в запросе. Синтаксиса для создания переменной имени таблицы нет.

Таким образом, вам придется использовать динамический SQL, даже если вы используете функцию DATABASE().

Percona Server ничем не отличается от СУБД Oracle для этой проблемы.

Ваши варианты этой проблемы:

  1. Stop с использованием нескольких схем для каждого клиента. Поместите все данные для каждого клиента в одну схему. Это кажется простым.

  2. Создайте хранимые процедуры уникальными для каждого клиента. Вы сказали, что не хотите этого делать. Но для чего это стоит, мы делаем это в хранимых процедурах и триггерах в клиентских базах данных, которыми я управляю на своей текущей работе. Это не так уж плохо. У нас есть «шаблонная» версия операторов CREATE для каждого триггера или процедуры с токеном-заполнителем для идентификатора клиента. Когда мы создаем базу данных нового клиента, мы копируем этот код шаблона и делаем замену на месте с идентификатором клиента, а затем запускаем его.

  3. Поместите данные ваших клиентов в их собственный эксклюзивный экземпляр MySQL Server. Таким образом, вы можете иметь несколько схем для каждого клиента, но имена схем не обязательно должны быть разными для каждого клиента. Вы можете запускать несколько экземпляров на одном сервере, их просто нужно настроить с помощью различных файлов данных, порта, sock_file и других файлов журналов.Хотя я видел, что это решение используется, я не рекомендую его, потому что у него много ресурсов, и с ним сложно справиться.

  4. Научитесь использовать динамический SQL.

1

Вы можете использовать PREPARED заявление в Procs так:

DELIMITER // 

CREATE PROCEDURE getPlace (OUT param1 char) 
BEGIN 
    SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO @sql; 
    PREPARE getPlaces from @sql; 
    EXECUTE getPlaces; 
    DEALLOCATE PREPARE getPlaces; 
END; 
// 

DELIMITER ; 

образец

MariaDB [mysql]> CREATE DATABASE Friends_clientOne; 
Query OK, 1 row affected (0.00 sec) 

MariaDB [mysql]> CREATE DATABASE Friends_clientTwo; 
Query OK, 1 row affected (0.00 sec) 

MariaDB [mysql]> CREATE DATABASE Places_clientOne; 
Query OK, 1 row affected (0.00 sec) 

MariaDB [mysql]> CREATE DATABASE Places_clientTWO; 
Query OK, 1 row affected (0.00 sec) 

MariaDB [mysql]> CREATE TABLE Places_clientOne.someTable (name varchar(32)); 
Query OK, 0 rows affected (0.02 sec) 

MariaDB [mysql]> CREATE TABLE Places_clientTwo.someTable (name varchar(32)); 
Query OK, 0 rows affected (0.02 sec) 

MariaDB [mysql]> INSERT INTO Places_clientOne.someTable VALUES('text in Places_clientOne.someTable'); 
Query OK, 1 row affected, 1 warning (0.00 sec) 

MariaDB [mysql]> INSERT INTO Places_clientTwo.someTable VALUES('text in Places_clientTwo.someTable'); 
Query OK, 1 row affected, 1 warning (0.01 sec) 

MariaDB [mysql]> use Friends_clientOne; 
Database changed 
MariaDB [Friends_clientOne]> DELIMITER // 
MariaDB [Friends_clientOne]> CREATE PROCEDURE getPlace (OUT param1 char) 
    -> BEGIN 
    ->  SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO @sql; 
    ->  PREPARE getPlaces from @sql; 
    ->  EXECUTE getPlaces; 
    ->  DEALLOCATE PREPARE getPlaces; 
    -> END; 
    -> // 
Query OK, 0 rows affected (0.03 sec) 
MariaDB [Friends_clientOne]> DELIMITER ; 

MariaDB [(none)]> use Friends_clientTwo; 
Database changed 
MariaDB [Friends_clientTwo]> DELIMITER // 
MariaDB [Friends_clientTwo]> 
MariaDB [Friends_clientTwo]> CREATE PROCEDURE getPlace (OUT param1 char) 
    -> BEGIN 
    ->  SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO @sql; 
    ->  PREPARE getPlaces from @sql; 
    ->  EXECUTE getPlaces; 
    ->  DEALLOCATE PREPARE getPlaces; 
    -> END; 
    -> // 
Query OK, 0 rows affected (0.02 sec) 

MariaDB [Friends_clientTwo]> DELIMITER ; 
MariaDB [Friends_clientTwo]> call getPlace(@r); 
+----------------------------------+ 
| name        | 
+----------------------------------+ 
| text in Places_clientTwo.someTab | 
+----------------------------------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

MariaDB [Friends_clientTwo]> use Friends_clientOne; 
Database changed 
MariaDB [Friends_clientOne]> call getPlace(@r); 
+----------------------------------+ 
| name        | 
+----------------------------------+ 
| text in Places_clientOne.someTab | 
+----------------------------------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

MariaDB [Friends_clientOne]> 
Смежные вопросы