WithCoderWithCoderWithCoder

在Think PHP5中切换MySQL数据执行相同的sql语句

    问题

    公司产品需要针对多个项目创建不同的MySQL数据库(数据库后缀相同),但共用一个PHP后台(后台框架使用Think PHP5)。每个项目的数据库中,用户、项目信息等数据表是存在一个公用库中,通过MySQL的FEDERATED引擎在不同项目库中引用。然后就碰到一个问题,每次修改共用的表后,对每个项目的数据库都要重新生成一次共用表。在数据库多的情况下,这样操作费时费力还容易出错。因此,就想通过程序,循环在多个数据库中执行同一sql语句,省时省力还不容易出错。

    失败的解决方法:

    因为技术原因,首先想到的是使用MySQL的存储过程,先把所有的数据库名称查询出来,然后使用游标,循环切换数据库执行sql。

    但在存储过程时发现,因为要切换数据库,使用use database时,提示“错误代码: 1314 USE is not allowed in stored procedures”。意思是在存储过程中不能使用“use”。这种方法宣告失败。

    在PHP中实现(基于Think PHP 5,所有数据库后缀为“tn.com”):

    思路如下:

    1. 查询information_schema.schemata表,返回所有的数据库名称数组   

// 查询所有数据库名称
$db_names = Db::query("SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE '%tn.com%';");

    2. 循环数据库名称数组,使用mysqli_connect连接数据库服务器

// 连接数据库服务器
$conn = mysqli_connect(config::get("database.hostname"), config::get("database.username"), config::get("database.password"));

    3. 切换数据库

// 切换数据库
$conn->select_db($v['schema_name']);

    3. 执行sql

// 执行(多条)sql
$res = $conn->multi_query($sql);

    4. 关闭数据库连接

// 关闭数据库连接
$conn->close();

    以上步骤,封装到一个方法中,如下:

/**
* 在多个数行同sql
* @param $sql
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
function execsql($sql)
{
   // 查询所有数据库名称
       $db_names = Db::query("SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE '%tn.com%';");

   foreach ($db_names as $k => $v) {
       // 连接数据库服务器
               $conn = mysqli_connect(config::get("database.hostname"), config::get("database.username"), config::get("database.password"));
       // 切换数据库
               $conn->select_db($v['schema_name']);
       // 执行(多条)sql
       $res = $conn->multi_query($sql);
       echo $v['schema_name'] . $res;
       echo '<br>';
       // 关闭数据库连接
               $conn->close();
   }
}

    在使用时,只需拼装好sql语句(可以多条,用分号“;”隔开),调用此方法即可。

    注意:

    实际调用时,发现mysqli_connect()方法需要在foreach内部调用,如果在外部调用,内部执行的sql只会在第一个库中执行,其他库执行不成功。

欢迎分享交流,转载请注明出处:WithCoder » 在Think PHP5中切换MySQL数据执行相同的sql语句