近期由于工作需要,需要做一个人口关系大图的存储及检索方案,我们主要的数据对象有:人口(年龄,身份证号码,性别。。) ;学校信息(学校地址,学校名称,学校级别,学校下边的年级班级。。);就职信息(公司名称,公司地址,公司企业信用代码。。)以及论文发布信息(论文主题,参与人,发布时间)

问题思考:

  1. 针对这类人口关系大图,或者叫图谱的数据一般都是非关系型,而且有多钟关系的存在,比如张三跟李四两个人,可能是同学,同事,老乡,配偶,夫妻,等多种关系,那一般如果采取关系型数据库(oracle)为例,可能就需要建立人员信息表, 同学关系表,同事关系表,老乡关系表,配偶关系表,夫妻关系表,这样一旦后续增加一个关系,就要增加一张表,增加一张表,而且后续数据库中就基本上只剩关系表了,后续的维护,扩充,代码的修改就机器的困难,简直就是噩梦。
  2. 通过上述的第一点,我们不难看出,采用关系型数据库来存储并不是最好的解决方案,那么就很容易想到采用关系型数据库存,那么目前比较流行的有哪些非关系型数据库么,redis,mongoDB,neo4j都能存储单个菲关系型的数据,但他们三者还是有区别的,前两者一般在项目中作为一个数据缓存的容器,将一些不经常变化的数据放在容器中,需者自取。而neoj4j专门用于网络图的存储,网络图,这个跟我们的项目需求不是不谋而合?于是心底暗自拍板,就你了 ,neo4j。

数据库设计:

通过关系表中存储的ID来进行关联;注意设置的时候是将与一个人所有关联的信息进行抽象出来并划分为五个对象,即上图的五个表单。 通过上图我们可以和明确的看出来有如下几种关系: 人 -就读->学校;

人 -发布论文->论文; 人-就职->企业; 人-居住->家庭;这四类的外部关系(以单个人节点为参照),另外一方面,人根根之间也是存在关系的,比如刚开始提到的同事,同学类的,那么这类属于内部关系,内部关系我们一般需要通过外部关系区分,比如张三和李四只有在同一个班级上学,那么菜算得上同学吧,只有在同一个公司就职才算得上同事吧.。这样的话,我们数据库设计出来,逻辑也梳理出来,尤其是内部关系外部关系。

实现方案:

我项目采用的是spring+springMvc的环境。

组件代码:

注意我是将neo4j的配置及实体放在一块的,至于其他的逻辑操作在其他的包中。

部分代码:

设置Configuration属性到neo4j中
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement; /***
*@ClassName AppConfiguration
*@desc TODO
*@Author xxxxxx
*@Date 2019/5/17 0017 下午 10:57
*@version 1.0.1
**/
@Configuration
@EnableNeo4jRepositories(basePackages = "com.audaque.module.graphData.neo4j.repos")
@EnableTransactionManagement
@ComponentScan("com.audaque.module.graphData.neo4j.config")
public class AppConfiguration extends Neo4jConfiguration {
@Autowired
private org.neo4j.ogm.config.Configuration config; @Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
return config;
}
@Override
@Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory(config,"com.audaque.module.graphData.neo4j.model");
}
@Override
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}

  

动态设置属性到Configuration中属性到中
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.authentication.UsernamePasswordCredentials;
import org.neo4j.ogm.config.Configuration; import static org.neo4j.ogm.config.DriverConfiguration.CREDENTIALS;
import static org.neo4j.ogm.config.DriverConfiguration.DRIVER;
import static org.neo4j.ogm.config.DriverConfiguration.URI; /***
*@ClassName MyConfiguration
*@desc 自定义bean动态配置neo4j数据源。
*@Author xiaokang.ma@audaque.com
*@Date 2019/5/24 9:14
*@version 1.0.1
**/
public class MyConfiguration extends Configuration {
public MyConfiguration(String driverClass,String driverURL,String userName,String password){
super.set(DRIVER[0],driverClass);
super.set(URI[0],driverURL);
super.set(CREDENTIALS[0],new UsernamePasswordCredentials(userName, password)); } }
PaperInfoRepository配置(实体的保存):
package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.PaperInfo;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.stereotype.Repository; /***
*@ClassName PaperInfoRepository
*@desc 论文信息接口
*@Author xxxx
*@Date 2019/5/17 0017 下午 5:43
*@version 1.0.1
**/
@Repository
public interface PaperInfoRepository extends GraphRepository<PaperInfo> { }

内部关系的Repository我采用的自定义查询语句查询,如下:

package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.Neo4jRelationInfo;
import org.neo4j.consistency.store.paging.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import java.util.Collection;
import java.util.List;
import java.util.Map; /***
*@ClassName Neo4jRelationInfoRepository
*@desc 八大关系型数据。
*@Author xxxx
*@Date 2019/5/17 0017 下午 5:43
*@version 1.0.1
**/
@Repository
public interface Neo4jRelationInfoRepository extends GraphRepository<Neo4jRelationInfo> { /**
* pe - pe 邻居关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:邻居{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_LJ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 同学关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:同学{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_TX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 校友关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) <- [r:校友{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_XY(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> li 居住关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:li) where a.ids={fromId} and b.ids={toId} merge (a) - [r:居住{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_JUZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 同事关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:同事{direction:{direction}}]-(b)")
Neo4jRelationInfo generateGraphDataRelation_TS(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> wu 就职关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:wu) where a.ids={fromId} and b.ids={toId} merge (a) - [r:就职{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_JZGX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> sc 毕业院校关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:sc) where a.ids={fromId} and b.ids={toId} merge (a) - [r:毕业{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_BYYX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pa 论文参与关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pa) where a.ids={fromId} and b.ids={toId} merge (a) - [r:参与者{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_PA(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pa 论文合作关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:论文合作{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_LWHZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询
*/
@Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid); /**
* web查询接口,查询与当前节点为1的数据
*/
@Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo); }

bean配置:

<!--初始化配置的Config-->
<bean id="myConfiguration" class="com.audaque.module.graphData.neo4j.config.MyConfiguration">
<constructor-arg name="driverClass" value="org.neo4j.ogm.drivers.http.driver.HttpDriver" index="0" type="java.lang.String"/>
<constructor-arg name="driverURL" value="http://10.229.183.142:7474" index="1" type="java.lang.String"/>
<constructor-arg name="userName" value="neo4j" index="2" type="java.lang.String"/>
<constructor-arg name="password" value="123456" index="3" type="java.lang.String"/>
</bean>

通过上述的简单配置就在spring环境中搭建到了neo4j。

业务逻辑代码:

  1. 存储所有的节点,直接读取数据中的人员信息,学校信息,居住信息,教育信息,工作信息,5张表的数据直接save到neo4j,部分代码如下.

  

 /**
* 初始化图数据需要的人员节点数据
*
* @param personBaseInfoRepository
* @return
*/
@Override
public void resetNeo4jPersonBaseInfoNode(PersonBaseInfoRepository personBaseInfoRepository) {
//查询人员节点列表
List<PersonBaseInfo> personBaseInfos = graphDataDao.queryPersonBaseInfo(); for (PersonBaseInfo personBaseInfo :personBaseInfos){
try {
personBaseInfoRepository.save(personBaseInfo);
}
catch (Throwable t){
//生成节点异常时,继续跳过。
continue;
}
}
}

初始化内部外部关心数据,代码如下:

 /********************************************开始初始化节点间关系的数据**********************************************/

    /**
* 初始化五大节点间的关系数据。
* @param neo4jRelationInfoRepository
* @return
*/
@Override
public void resetAllRelationInfo(Neo4jRelationInfoRepository neo4jRelationInfoRepository) {
long start = System.currentTimeMillis();
//初始化人员-->工作关系,人员->学校;人员->论文;人员->住房信息4个主关系的数据。
List<Map<String,Object>> lists = graphDataDao.queryEntityRelationInfo();
//计算内部关系信息 ,同事,校友,邻居,合作者关系。
Map<String,List<String>> schoolFriendMap = new ConcurrentHashMap<>(); //校友 Map<String,List<String>> workTogetherMap = new ConcurrentHashMap<>(); //同事 Map<String,List<String>> neighborMap = new ConcurrentHashMap<>(); //邻居
Map<String,List<String>> collaboratorMap = new ConcurrentHashMap<>();//论文合作者
for(Map<String,Object> map :lists){ String userId = "";
//获取人员信息
if(StringUtils.isNoneEmpty((String)map.get("USERID")) && StringUtils.isNoneEmpty((String)map.get("USERNAME"))){
//取工作单位字段 UNIT_ID , UNIT_NAME
if(StringUtils.isNoneEmpty((String)map.get("UNIT_ID")) && StringUtils.isNoneEmpty((String)map.get("UNIT_NAME"))){
//插入就职关系
neo4jRelationInfoRepository.generateGraphDataRelation_JZGX((String)map.get("USERID"),(String)map.get("UNIT_ID"),(String)map.get("USERID")+"->"+(String)map.get("UNIT_ID")); //处理同事关系
if(workTogetherMap.containsKey((String)map.get("UNIT_ID"))){
List<String> list = workTogetherMap.get((String)map.get("UNIT_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
workTogetherMap.put((String)map.get("UNIT_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
workTogetherMap.put((String)map.get("UNIT_ID"),lis);
} }
//取学校字段 SCHOOL_ID , SCHOOL_NAME
if(StringUtils.isNoneEmpty((String)map.get("SCHOOL_ID")) && StringUtils.isNoneEmpty((String)map.get("SCHOOL_NAME"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_BYYX((String)map.get("USERID"),(String)map.get("SCHOOL_ID"),(String)map.get("USERID")+"->"+(String)map.get("SCHOOL_ID")); //处理校友关系
if(schoolFriendMap.containsKey((String)map.get("SCHOOL_ID"))){
List<String> list = schoolFriendMap.get((String)map.get("SCHOOL_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
schoolFriendMap.put(this.schoolFriend,list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
schoolFriendMap.put((String)map.get("SCHOOL_ID"),lis);
} } //取住房信息字段 HOUSE_ID , HOUSE_ADDR
if(StringUtils.isNoneEmpty((String)map.get("HOUSE_ID")) && StringUtils.isNoneEmpty((String)map.get("HOUSE_ADDR"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_JUZ((String)map.get("USERID"),(String)map.get("HOUSE_ID"),(String)map.get("USERID")+"->"+(String)map.get("HOUSE_ID")); //处理邻居关系
if(neighborMap.containsKey((String)map.get("HOUSE_ID"))){
List<String> list = neighborMap.get((String)map.get("HOUSE_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
neighborMap.put((String)map.get("HOUSE_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
neighborMap.put((String)map.get("HOUSE_ID"),lis);
}
}
//取论文信息字段 LW_ID , LW_TITLE
if(StringUtils.isNoneEmpty((String)map.get("LW_ID")) && StringUtils.isNoneEmpty((String)map.get("LW_TITLE"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_PA((String)map.get("USERID"),(String)map.get("LW_ID"),(String)map.get("USERID")+"->"+(String)map.get("LW_ID"));
//处理合作者关系
if(collaboratorMap.containsKey((String)map.get("LW_ID"))){
List<String> list = collaboratorMap.get((String)map.get("LW_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
collaboratorMap.put((String)map.get("LW_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
collaboratorMap.put((String)map.get("LW_ID"),lis);
}
} }
} //开始剔除长度为1的数据,没有对应的关系。
schoolFriendMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
schoolFriendMap.remove(key);
}
});
workTogetherMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
workTogetherMap.remove(key);
}
});
neighborMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
neighborMap.remove(key);
}
});
collaboratorMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
collaboratorMap.remove(key);
}
}); //开始遍历校友关系数据,生成节点。
schoolFriendMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_XY(li.get(st),li.get(ss),"<->"); }
}
});
//同事关系
workTogetherMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_TS(li.get(st),li.get(ss),"<->"); }
}
});
//邻居关系
neighborMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_LJ(li.get(st),li.get(ss),"<->"); }
}
});
//合作者关系
collaboratorMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_LWHZ(li.get(st),li.get(ss),"<->"); }
}
});
System.out.println("总共花费时间:" + (System.currentTimeMillis() - start) + "ms"); }

然后Control中对外暴露三个接口, 1.初始化节点,  2.初始化关系。 就可以了。

然后通过浏览器直接可以看到图数据的结构,分享下我做出来的效果。

至此一个从数据库存入到neo4j数据库中,然后可以对外开放一个查询的接口,返回与之有关系并且深度为1的数据,方便其他系统展示,接口如下:

/**
* web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询。
*/
@Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid); /**
* web查询接口,用户登录之后第一次查询,需根据身份证号码查询。第二次查询就直接会调用上一个查询。
*/
@Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo);

基于neo4j图数据库,实现人口关系大图的基本思路及实现方案。的更多相关文章

  1. Neo4j图数据库管理系统开发笔记之一:Neo4j Java 工具包

    1 应用开发概述 基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发.封装的重点,是解决Neo4j嵌入式版本Emb ...

  2. Neo4j图数据库从入门到精通

    目录 第一章:介绍 Neo4j是什么 Neo4j的特点 Neo4j的优点 第二章:安装 1.环境 2.下载 3.开启远程访问 4.启动 第三章:CQL 1.CQL简介 2.Neo4j CQL命令/条款 ...

  3. Neo4j图数据库从入门到精通(转)

    add by zhj: 转载时,目录没整理好,还会跳转到原文 其实RDB也可以存储多对多的关系,使用的是中间表,GDB使用的是边,RDB中的实体存储在数据表,而GDB存储在节点.两者使用的底层技术不同 ...

  4. 使用neo4j图数据库的import工具导入数据 -方法和注意事项

    背景 最近我在尝试存储知识图谱的过程中,接触到了Neo4j图数据库,这里我摘取了一段Neo4j的简介: Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌 ...

  5. Neo4j资料 Neo4j教程 Neo4j视频教程 Neo4j 图数据库视频教程

    课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,<Neo4j ...

  6. Neo4j视频教程 Neo4j 图数据库视频教程

    课程名称 课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,< ...

  7. Ubuntu16.04下Neo4j图数据库官网安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu LTS \n \l r ...

  8. Ubuntu14.04下Neo4j图数据库官网安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu 14.04.4 LTS ...

  9. Neo4j教程 Neo4j视频教程 Neo4j 图数据库视频教程

    课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,<Neo4j ...

随机推荐

  1. 搭建Node.js Redis开发环境

    创建项目 初始化为node项目 $npm init   安装redis   安装@types/node, @types/redis, typescript   初始化TypeScript   配置ts ...

  2. 《疯狂动物城》主题曲《TryEverything》中文翻译

    <疯狂动物城>主题曲<TryEverything>夏奇拉激情献唱,很多事情是需要是试试,不试试就不知道可以成功. Oh oh oh oh oooh 哦哦哦哦哦 Oh oh oh ...

  3. Spring cloud Eureka 服务治理(搭建服务注册中心)

    服务之类是微服务架构中最为核心的基础模块,它主要用来实现各个微服务实例的自动化注册和发现. 1. 服务注册 在服务治理框架中,通常会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机. ...

  4. 【Java】Maven 常用命令

    Maven 常用命令 mvn compile 编译,生成target文件夹,里边有classes文件夹,存放.class文件 mvn test 执行测试 mvn package 打包,在targert ...

  5. AI software can catch shoplifters before they steal

    日本研发出智能软件 不等下手就能识别小偷 AI software can catch shoplifters before they steal 在汤姆·克鲁斯主演的电影<少数派报告>中, ...

  6. MATLAB之画确定区域内不重合的随机圆

    MATLAB之画确定区域内不重合的随机圆 程序要求:在确定区域内,画互不重合的圆. 知识点: (1)A=p'; 转置运算 (2)ones(a,b)产生a行b列全1数组 (3)rand(a,b)产生a行 ...

  7. SqlServer查询文件组被占用情况

    在SqlServer中,删除一个文件组 alter database [xxxxx] remove filegroup FGMonthTurnIntroduceByMonth13 有时候会遇到如下报错 ...

  8. Oracle数据库基础--SQL查询经典例题

    Oracle基础练习题,采用Oracle数据库自带的表,适合初学者,其中包括了一些简单的查询,已经具有Oracle自身特点的单行函数的应用 本文使用的实例表结构与表的数据如下: emp员工表结构如下: ...

  9. SQLSERVER 创建ODBC 报错的解决办法 SQLState:'01000'的解决方案

    错误详情如下: SQLState:'01000' SQL Server 错误:14 [Microsoft][ODBC SQL Server Driver][DBNETLIB] ConnectionOp ...

  10. 真实场景中WebRTC 用到的服务 STUN, TURN 和 signaling

    FQ收录转自:WebRTC in the real world: STUN, TURN and signaling WebRTC enables peer to peer communication. ...