How access data between databases in mysql? - mysql

I'm working in a project that is divided into multiple modules. Each module have it's own independent database in mysql, but now, the modules need to obtain data between them. For example we're going to develop a new "admin" module, and every other modules need to access the data in the "admin" database. I know that I can make a query like
select * from admin.table
to obtain data from other database, but each module (and the new "admin" module) are created in CakePHP. I think one possible solution is use something like Synonyms (like the ones in Oracle or SQL Server), but MySQL don't support it. Someone have a better idea? Thanks

I have a feeling CakePHP can handle cross-database relations. Try setting $useDbConfig for each model to a connection for the respective database. CakePHP should generate multiple queries (atleast one per database connection) and join the results together for you. This approach should work fine for simple relations, but there might not be full support for relations such as HABTM.

How about using views:
create view admin_table as select * from admin.table
Then, you just need to set $tableName to admin_table.

I may be wrong, but I think querying is based on
select * from database.owner.table ... and the implied owner would be the "dbo" (database owner). So, you MIGHT be able to do the following...
select a1., b1. from database1.table1 a1, database2.table2 b1 where a1.fld1 = b1.fld1 ...

Related

Using doctrine with multiple MySQL Databases

I'm starting a new project from an existing MySQL DB and I would like to use symfony+doctrine for that.
The problem is that my current DB has multiple DB in it. For instance, it has db.tables like:
customers.info
customers.orders
items.catalog
items.stock
etc....
I've tried to search online but I've realized that one of the problem is that "database" word is used to define 2 very different things: database "software", like mysql, postgres, mariaDB, etc... and databases as in SQL "CREATE DATABASE".
So when I'm looking at symfony doc, I found this page, which states that I cannot use Doctrine ORM since I have multiple DB: https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
But the more I read it, the more I have the feelings that what there are saying is "you need one entityManager for Mysql, one for Postgres, etc... and Entities cannot define associations across different entity managers" and not "Entities cannot define associations across different DB from the same DB software"
AM I right? and if yes, how can I achieve such a thing, knowing that I need to provide a database name in the connection URL (like mysql://user:pass#127.0.0.1/oneOfMyDb )
Thanks!
Ok so I finally found the answer, which may be useful for other people in the same situation.
It is possible to use doctrine with multiple database/schema in mySQL. yes, the problem here is that MySQL kinda mixed the concept of DB and schema, hence the confusion.
In order to do this, you need to declare the table and schema used for every entity, for instance:
<?php
namespace App\Entity;
use App\Repository\PropertyRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=PropertyRepository::class)
* #ORM\Table(name="property", schema="myOtherDB")
*/
class Property
{
// some stuff here...
}
This way, no matter which DB name you declare in the connection, it will connect to you other DB (schema) and you will be able to fetch datas from foreign keys, even if this data is stored in a table in a different DB (schema).
I hope this will help some people!

Coldfusion server mapping to sql server

I have a ColdFusion server connected to MySQL database. Now I am changing the database to an existing MSSql server .. MSSql server has a similar database that of MySQL but the table names and column names are different. My question is that how can I map the new MSSql server to the ColdFusion server without changing the ColdFusion code.. Means without changing the table name and column names in ColdFusion code..
Thanks in advance
If the schemas are different (different column names and number of columns) then you probably have no choice but to refactor your CF code to reflect the new MSSQL schema. If there is a one to one relationship between the table and column names from one DB to the next you could use views - but it would make for a very confusing development environment. Again... each table would have to "match" for number of columns and types of data. Example
Old table "users"
firstname, lastname address
New table "tblUsers"
fname, lname, addr
Given the schemas above, you might have a query in your CF Code that looked like:
<cfquery name="getUsers" datasource="blah">
SELECT firstname, lastname, address
</cfquery>
So it would fail when you switched the DB. However, if you created a view like so:
CREATE VIEW [dbo].[Users]
AS
SELECT u.fname AS firstname,
u.lname AS lastname
u.addr AS address
FROM dbo.tblusers
Then your code would work. Again I am NOT recommending this. Your best course of action is to alter the schema to reflect your code or to refactor your code to work against the new schema. But technically it does answer your question :)
Unless you're already using ORM, here is no handy function or mapping mechanism in CF that would allow you to do this. There may be some manipulation at the driver level, or dipping into the java code that creates the sql strings to do text parsing there, but that's outside of my realm of expertise.
My guess, though, is that you have a lot of queries scattered throughout the application and are therefore daunted at the task of redoing all of them. Personally, I would refactor at least the data access of this app into one or more .cfc's. Even if all you do is wrap each query into a function call and replace the cfquery code with a function call, you're consolidating all of the database calls into one place and can change things much easier going forward.

What is the best way to filter a multi-tenant MySQL database?

In MySQL I have a single database with one schema. In Microsoft Sql Server it is recommended to use a "Tenant View Filter" so in Microsoft Sql Server this gives me exactly what I need.
CREATE VIEW TenantEmployees AS
SELECT * FROM Employees WHERE TenantID = SUSER_SID()
What is the best way to accomplish the same in MySQL? An equivalent to the "Tenant View Filter" will work if it is performs well.
Thanks!!
The query you suggest (that I could find in MSDN) has text afterwards that explains exactly what are its assumptions. In particular, it mentions that it assumes that the "owner" of a row in the Employees table is specified in the TenantID field that is populated according to the SID of the user(s) you are partitioning for.
What that means is that you can replicate the same idea whatever way you decide to implement your data as long as you have clearly defined partitions of the data and know exactly how to associate it with the table you are creating a view for.
In particular, if you configure your system so that each partition accesses the DB with its own credentials, you could use the CURRENT_USER or USER constructs of MySQL as the IDs defining your partitions and the query to create the view would be basically the same as the one suggested in MSDN replacing SUSER_ID with CURRENT_USER.
But if you use the same user to access from all the partitions, then the suggested method is irrelevant on either database server.
Since you need to use your tenantId value to perform filtering, a table valued user defined function would be ideal, as a view normally does not accept parameters. Unfortunately, unlike many other database products MySQL doesn't support table-valued functions. However, there are MySQL hacks that claim to emulate parametrized views. These could be useful for you.
It's a little tricky in MySQL, but it can be done:
CREATE OR REPLACE VIEW {viewName}
AS
SELECT {fieldListWithoutTenantID}
FROM {tableName}
WHERE (id_tenant = SUBSTRING_INDEX(USER( ),'#',1))
I wrote up a full blog post on how I converted a single-tenant MySQL application to multi-tenant in one weekend with minimal changes. https://opensource.io/it/mysql-multi-tenant/

Is it possible to get information from different database with inner join having database in SQL and mySql?

I have my project A with mySql database and I have another project B with msSql. I have connected the database from A and fetched data from B. But now I need to use inner join for tables in A and B. Is it possible to do so with databases in the same server and different server? Any help will be appreciated.
Thanks in advance
Yes, it should be possible. First, you will need to link your MySQL server to your MS SQL Server.
See this reference. Secondly, you will probably need to use sub queries to select the correct columns and do the join on them;
SELECT *
FROM
(SELECT ms_column1, ms_column2 FROM MSSQLTABLE) AS mssql
JOIN
(SELECT my_column1, my_column2
FROM openquery(LINKED_SERVER, 'SELECT column1, column2 FROM MYSQLTABLE') AS mysql
ON mssql.ms_column1 = mysql.my_column1
Unfortunately untested.
Instead of making the two different databases communicate between themselves you can move the logic of the communication to the programming layer. For example using PDO and PHP you can connect to both databases, get the data, mix it and produce a result. You can create an abstraction layer of PHP classes that get information independently from A or B databases, and later you will not care anymore about it, as you will work with PHP objects not directly with databases.

Using a table in another database

I've been asked to build a module for a web application, which will also be used as a stand alone website. Since this is the case, I wanted to use a separate database, and wondered if there was a way of having a table in one database, be a "pointer" in another database.
For example, I have databases db1 and db2
db1 has table users, so I want to have db2.users point to db1.users.
I know I could setup triggers and what not to sync two seperate tables but this sounds cooler :)
EDIT
So in my code I'm using sql such as
select * from users
Now, at the database level, I want "users" to actually be db1.users. Then, if I want to, I can remove the alias/pointer and "select * from users" will point to the users table in the current database. I guess what I'm looking for is a "global alias" type of thing.
Just use it directly from another database?
SELECT ... FROM `db1`.`users` LEFT JOIN `db2`.`something`
The federated storage engine offers something similar to the feature you asked for.
And if your databases are on the same database server, the federated storage enging sounds a bit like an overkill to me. You may want to create a view instead.
Both methods won't be useful if db1 is not available. As Emmerman already points out, you need to store the data in db2 if you want to prepare for the case of db1 being unavailable.