如图 电影movie有多个附表,如果通过movie表来找出多个与之关联的表。

本算法规则:

  1. 外键写法必须是X_id;
  2. A与B 1对多关系,中间表表名必须是A_B,且A_B,必须包含A_id,B_id外键;

算法如下:

---------------------更新-----------------------------------------------

 function findRelation($db=['dbname','user','pwd','host'],$current,$father='')
{
static $pdo;
if(empty($father))
{
$pdo=new PDO("mysql:host=".(isset($db[3])?$db[3]:'localhost').";dbname={$db[0]}",$db[1],(isset($db[2])?$db[2]:''));
$pdo->exec('set names utf8');
} //临时数组,保存下面运行得出的数据
$tp=[]; //当前表的所有字段信息
$self=$pdo->query('show full columns from '.$current); //当前表是否中间表
$is_middle=0; //检查当前表是否有附表id字段
while($row = $self -> fetch())
{
//如果有发现以xxx_id命名的外键
if(stripos($row['Field'],'_id')!==FALSE)
{
//获取附表名
$extName=str_ireplace('_id','',$row['Field']); //如果当前的”附表“ 名是父表名,记录保存字段
if($extName==$father)
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'parent_index']; continue;
}
else
{
//当前表包含有 当前表外键中的附表名(即main_extName 包含有 extName_id),则此表为中间表
if(strpos($current,$extName)!==FALSE)
$is_middle=1; //记录字段信息
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'next_index']; //继续往下寻找附表关系
           $tp[$extName]=findRelation($db,$extName,$current); }
}
else//没发现外键,记录当前字段
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],$row['Key']];
}
} //记录当前表是否中间表
if($is_middle)
$tp['_type']='middle';
else
$tp['_type']='content'; //获取当前表注释
$cms=$pdo->query("show table status from {$db[0]} where name='{$current}'");
$one=$cms->fetch();
$tp['_comment']=$one['Comment']; //扫描以【当前表】_为开头的附表
$exts=$pdo->query('show tables like "'.$current.'_%"');
while($ext = $exts -> fetch())
{
//往下寻找当前表与每个附表的关系
$tp[$ext[0]]=findRelation($db,$ext[0],$current);
} return $tp;//返回已记录的关联关系和字段信息
} echo '<pre>';
print_r(['movie'=>findRelation(['movieshop','root'],'movie')]);
echo '</pre>';

上述算法得出的数据格式如下:

/*

([主表]=>)[
[_field]=>[
[字段名] => [
[0] => 字段类型
[1] => 默认值
[2] => 字段注释
[3] => 字段索引
],
.....
]
, [_type]=>middle/content(多对多中间表/1对多内容表,不是中间表可忽略)
,
[_comment]=>表注释
,
[附表名]=>[
[_field]=>[
[字段名] => [
[0] => 字段类型
[1] => 默认值
[2] => 字段注释
[3] => 字段索引
],
.....
],
[_type]=>middle/content(多对多中间表/1对多内容表,不是中间表可忽略)
,
[_comment]=>表注释
,
[附表名]=>[
.............
]
,
...............
]
,
..........
] */

------------------------------------------------------------------------------旧版---------------------------------------------------------------------------------------

<?php

/*
2016-11-03
GaZeon -------------寻找表关系方法--------------- 主表:main 附表格式:main_extName 可能存在的表:extName 判断主附的对应关系方法: 如果main 有 extName_id 则 main与main_extName 为1对1关系 如果main_extName 【有 且只有 main_id外键】或 【main_extName 有其他外键但不包含extName_id外键 】 则 main与main_extName 为1对多关系 如果main_extName 有 main_id外键,且有 extName_id 外键,则 main与 extName为多对多关系 ,main_extName为中间表 与main为1对多关系 1,获取【当前表】的所有字段,并循环字段查找_id结尾的外键
{
2,如果查找到【当前表】的外键,则判断【外键所在的表】是否【当前表】的【上一级表】:
[如果是,则【外键所在的表】为中间表,【当前表】与【外键所在的表】为1对多关系,跳过本次进入下次循环];
[如果不是,则【当前表】与【外键所在的表】为1对多关系,查找这个【外键所在的表】],
}
3,【当前表】外键查找完后,扫描以【当前表】_为开头的表:
[如果有,则循环轮流进入1程序];
4,没有,当前关联关系到达最终点,返回本次运行得出的关系信息。 -----------------------------------------------------
如果一个表没有任何外键
如果这个表没有附表,则为最终表
如果这个表有附表,则查找其附表,继续寻找其表的关联关系 */
$pdo=new PDO('mysql:host=localhost;dbname=MovieShop','root','');
$pdo->exec('set names utf8');
$relation=[]; function findRelation($current,$father='')
{
global $pdo;
global $relation; //临时数组,保存下面运行得出的数据
$tp=[]; //当前表的所有字段信息
$self=$pdo->query('show full columns from '.$current); //当前表是否中间表
$is_middle=0; //检查当前表是否有附表id字段
while($row = $self -> fetch())
{
//如果有发现以xxx_id命名的外键
if(stripos($row['Field'],'_id')!==FALSE)
{
//获取附表名
$extName=str_ireplace('_id','',$row['Field']); //如果当前的”附表“ 名是父表名,记录保存字段
if($extName==$father)
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],'parent_index']; continue;
}
else
{
//当前表包含有 当前表外键中的附表名(即main_extName 包含有 extName_id),则此表为中间表
if(strpos($current,$extName)!==FALSE)
$is_middle=1; //记录字段信息
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],'next_index']; //继续往下寻找附表关系
$tp[$extName]=findRelation($extName,$current); }
}
else//没发现外键,记录当前字段
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Key']];
}
} //记录当前表是否中间表
if($is_middle)
$tp['_type']='middle';
else
$tp['_type']='content'; //扫描以【当前表】_为开头的附表
$exts=$pdo->query('show tables like "'.$current.'_%"');
while($ext = $exts -> fetch())
{
//往下寻找当前表与每个附表的关系
$relation[$current][$ext[0]]=findRelation($ext[0],$current);
} return $tp;//返回已记录的关联关系和字段信息
} findRelation('movie'); echo '<pre>';
print_r($relation);
echo '</pre>';

有bug请联系本人,转载需注明出处。

PHP获取某个表与其他表的关联关系算法的更多相关文章

  1. [js开源组件开发]query组件,获取url参数和form表单json格式

    query组件,获取url参数和form表单json格式 距离上次的组件[js开源组件开发]ajax分页组件一转眼过去了近二十天,或许我一周一组件的承诺有了质疑声,但其实我一直在做,只是没人看到……, ...

  2. 获取SQLSERVER所有库 所有表 所有列 所有字段信息

    最近想起来做一个项目代码生成器,直接生成底层代码.. 这免不了要先行读取数据库已有的信息.. 废话不多说..开整.. SELECT NAME FROM MASTER..SYSDATABASES --读 ...

  3. SQL获取所有数据库名、表名、储存过程以及参数列表

    SQL获取所有数据库名.表名.储存过程以及参数列表 1.获取所有用户名:SELECT name FROM Sysusers where status='2' and islogin='1'islogi ...

  4. sql 2000以及2005以上获取数据库中所有的表(不包括系统表)

    ---------------------------------------------------------------------------- --sql 2005以上数据库 --- 获取数 ...

  5. jquery不能是使用普通的for循环 因为普通的for循环通过下表获取对象 如果通过下表获取对象的话 会转成dom对象

    jquery不能是使用普通的for循环 因为普通的for循环通过下表获取对象 如果通过下表获取对象的话 会转成dom对象

  6. Oracle 获取 某个表的建表SQL

    获取A表的创表SQL select dbms_metadata.get_ddl('TABLE','A') from dual

  7. Sqlserver获取所有数据库名,表信息,字段信息,主键信息,以及表结构等。

    --获取所有数据库名: SELECT name FROM master..sysdatabases WHERE name NOT IN ( 'master', 'model', 'msdb', 'te ...

  8. sql脚本来获取数据库中的所有表结构了

    sql脚本来获取数据库中的所有表结构了,代码如下: use AdventureWorks2008 go SELECT (case when a.colorder=1 then d.name else ...

  9. SqlServer中获取所有数据库,所有表,所有字段

    原文:SqlServer中获取所有数据库,所有表,所有字段 一.获取所有数据库 select * from master.dbo.SysDatabases 二.获取某个库中所有表 SELECT * F ...

随机推荐

  1. 题目:解决.NET项目中的平台选项,由x86设置为AnyCPU

    问题:开发出的.NET程序在windows7 X64平台无法使用,打开提示异常”stopping work….” 1.打开解决方案中的配置管理器,发现有部分程序集的平台是x86,想改变平台选项,发现无 ...

  2. [Android]Android开发入门之HelloWorld

    引言:在做Unity开发的时候,发现这么个问题,虽然Unity是跨平台的,能够进行Android,IOS,Web,PC等开发,但如果要实现一些稍微系统层的东西,还是需要通过通信,调用原系统的接口(自定 ...

  3. x64内核内存空间结构

    0x00 前言 本文主要是讨论Windows 7 x64下的内核虚拟地址空间的结构,可以利用WiinDBG调试的扩展命令"!CMKD.kvas"来显示x64下的内核虚拟地址空间的整 ...

  4. STM32解密STM32F103芯片解密STM32F103R6单片机破解多少钱?

    STM32解密STM32F103芯片解密STM32F103R6单片机破解多少钱? STM32F系列单片机芯片解密型号: STM32F100  |  STM32F101  |  STM32F102  | ...

  5. border

    1.border-width:不支持百分比值 支持下面属性值: thin:1px medium:3px thick:5px 2.border-style类型 solid:实线 dashed:虚线(方形 ...

  6. SOAPUI测试步骤----DataGen TestStep

    DataGen TestStep DataGen TestStep可以用来生成数据输入在你 TestCases ,例如数字或日期序列.随机选择等生成的数据作为属性,因此可以转移 和扩张就像任何其他属性 ...

  7. JS 生成GUID 方法

    var Guid={NewGuid: function () { var guid = (this._G() + this._G() +"-"+ this._G() +" ...

  8. docker 配置文件引发的问题

    好久没有配置 vmware / harbor 了,突然间来了兴趣,结果让我失望了,登陆反复的被refused; 这个是配置文件地址:https://github.com/vmware/harbor/b ...

  9. java 对象输入输出流

    对象的输入输出流的作用: 用于写入对象 的信息读取对象的信息. 对象的持久化. 比如:用户信息.              ObjectInputStream   : 对象输入流            ...

  10. HTML 5 拖放(Drag 和drop)

    浏览器支持 Internet Explorer 9.Firefox.Opera 12.Chrome 以及 Safari 5. 1.把标签 draggable 属性设置为 true. 2.向标签添加on ...