将 SQL 数据库中的约束提取到 PHP 中的 JSON

Posted

技术标签:

【中文标题】将 SQL 数据库中的约束提取到 PHP 中的 JSON【英文标题】:Fetching constraints in SQL database to JSON in PHP 【发布时间】:2019-08-07 16:30:54 【问题描述】:

假设我有以下汽车制造商和相应汽车的数据库结构:

制造商:

----------------------------------
| manufacturer | founded_in | id |
|--------------|------------|----|
| Daimler AG   | 1927       | 1  |
| Volkswagen AG| 1937       | 2  |
----------------------------------

汽车:

-------------------------------------
| car     | built_in | manufacturer |
|---------|----------|---------------
| C Class | 1993     | 1            |
| E Class | 1993     | 1            |
| Golf    | 1974     | 2            |
-------------------------------------

manufacturersid 列是主键,carsmanufacturer 列有对应的外键约束。

我想使用 php json_encode 生成以下 JSON 输出:


    "manufacturers": 
        "Daimler AG": 
            "founded in": "1927",
            "cars": [
                "C Class",
                "E Class"
            ]
        ,
        "Volkswagen AG": 
            "founded in": "1937",
            "cars": [
                "Golf"
            ]
        
    

为了让制造商和他们的founded_in 我只是执行:

SELECT manufacturer, founded_in FROM manufacturers

并将它们提取到一个数组中。但是,在进行第二次查询后,如何正确分配汽车?

【问题讨论】:

我猜你可以通过内部连接来做到这一点。 怎么样?我需要一次将多辆汽车分配给一个制造商。 【参考方案1】:

您还可以使用对象关系映射器,例如 Respect/Relational

您可以简单地调用:

use Respect\Relational\Mapper;

$mapper  = new Mapper(new PDO($db_string, $db_user, $db_pass));
$results = $mapper->manufacturers->cars->fetchAll();
$json    = json_encode($results);

把繁重的工作交给 API。

【讨论】:

【参考方案2】:

如果您使用的是 mysql 5.7 或更高版本,则可以使用 JSON 聚合函数直接从 SQL 查询生成您期望的输出。我希望这会比在两者之间使用 php 更有效。

首先,考虑以下聚合查询,JOINs 两个表并为每个制造商创建一个 JSON 对象,并在子数组中包含相关汽车名称的列表:

SELECT JSON_OBJECT('founded in', m.founded_in, 'cars', JSON_ARRAYAGG(c.car)) js
FROM manufacturers m
INNER JOIN cars c ON c.manufacturer = m.id
GROUP BY m.id, m.founded_in;

这会返回:

| js                                                   |
| ---------------------------------------------------- |
| "cars": ["C Class", "E Class"], "founded in": 1927 |
| "cars": ["Golf"], "founded in": 1937               |

要产生预期的输出,我们可以将其转换为子查询并添加另一个级别的聚合:

SELECT JSON_OBJECT('manufacturers', JSON_OBJECTAGG(manufacturer, js)) myjson
FROM (
    SELECT 
        m.id, 
        m.manufacturer, 
        JSON_OBJECT('founded in', m.founded_in, 'cars', JSON_ARRAYAGG(c.car)) js
    FROM manufacturers m
    INNER JOIN cars c ON c.manufacturer = m.id
    GROUP BY m.id, m.manufacturer, m.founded_in
) x

这会产生:

| myjson                                                                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------------------------ |
| "manufacturers": "Daimler AG": "cars": ["C Class", "E Class"], "founded in": 1927, "Volkswagen AG": "cars": ["Golf"], "founded in": 1937 |

Demo on DB Fiddle

【讨论】:

【参考方案3】:

可以先查询所有数据

SELECT m.manufacturer, m.founded_in
  FROM manufacturers AS m
  JOIN cars AS c ON c.manufacturer_id = m.id

然后将其转换为你在 php 中的结构

$manufacturers = [];
foreach ($rows as $row) 
    if (!array_key_exists($row['manufacturer'], $manufacturers)) 
        $manufacturers[$row['manufacturer']] = array(
           'founded_in' => $row['founded_in'],
           'cars' => array());
    

    array_push($manufactureres[$row['manufacturer']]['cars'], $row['car']);


当然,在 php 中有一种更实用的方法可以做到这一点,但你应该可以这样做......

【讨论】:

那么您是否建议我应该加入两个表,这些表中的制造商列中的所有行都已填充,即使我只有两个?这算是好的做法吗? 嗯,这取决于你有多少数据。您也可以有两个单独的查询,并填充相同的结构。 作为一种习惯,你可以说,让数据库来处理这一切,因为它是为这样的东西而生的。如果成本太高,您可以将虚假值填充到测试数据库中并运行基准测试。

以上是关于将 SQL 数据库中的约束提取到 PHP 中的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

在日期范围SQL之间选择PHP脚本中的数据[重复]

将 SQL 表中的所有数据提取到我的 Python 代码中

将xml中的数据提取到SQL Server表中

外键约束

sqlserver2005,如何将一个数据库中的所有表的数据清空,而约束不删?跪求答案

将数据从 SAP 提取到 SQL Server