Java下拼接执行动态SQL语句(转)

时间:2022-09-22 20:01:11

在实际业务中经常需要拼接动态SQL来完成复杂数据计算,网上各类技术论坛都有讨论,比如下面这些问题:

http://bbs.csdn.net/topics/390876591

http://bbs.csdn.net/topics/390981627

https://www.linkedin.com/groups/SQL-Query-Help-needed-137774.S.5948812806903119877?trk=groups_items_see_more-0-b-ttl

http://bbs.csdn.net/topics/390073758

http://bbs.csdn.net/topics/390611005

拼接动态SQL的一般做法有

      1、使用动态语句

很多数据库都提供了处理动态SQL的语法,如Oracle的EXECUTE IMMEDIATE语句、MSSQL的EXEC和SP_EXECUTESQL、Mysql的预处理语句等。这些功能让我们在数据库端来处理动态查询提供了极大遍历,但这种方式只适用于相对简单地动态查询,复杂的情况经常会采用下面的方式。

2、使用存储过程

对于复杂的情况,一般会在存储过程中来拼接动态SQL。使用存储过程完成相对灵活,但编码复杂度过高,有时运行效率较低。

3、使用其他(如JAVA)程序

使用外部的其他高级语言(如JAVA)拼接后再交由数据库执行也是一种选择,其灵活性较高,但由于JAVA缺乏对集合计算的支持,完成这些准备工作并不轻松。

如果需要执行动态SQL的主控程序是JAVA的,那么可以使用集算器来协助完成动态SQL类计算,集算器是动态解释执行的脚本,可以方便地拼出动态SQL执行。集算器提供了JDBC接口,可以置于Java应用程序与数据库之间,让应用程序继续象访问数据库一样执行集算器脚本,应用结构几乎不用改变。

下面通过例子来说明如何使用集算器完成动态SQL类计算,并集成进JAVA程序。

拼接动态SQL

在集算器中完成动态SQL拼接,并将拼接后的SQL再交由数据库执行,以查询出目标结果。集算器在完成时并不涉及目标计算,只拼接动态SQL。如下面的需求:

参数source和target代表两个结构相同但数据不同的表,但表结构未知。要求以主键为标准用source更新target,比如table1和table2的主键都是A和B,数据如下:

用table2更新table1时,MERGE语句应当如下:

MERGE INTO table1 as t

USING table2 as s

ON t.A=s.A and t.B=s.B

WHEN MATCHED

THEN UPDATE SET t.C=s.C,t.D=s.D

WHEN NOT MATCHED

THEN INSERT VALUES(s.A,s.B,s.C,s.D)

实现脚本:

A1,A2: 从系统表中读出表source的主键存入变量pks,计算结果为集合["A","B"]。各种数据库获得主键的方法不同,这里以MSSQL为例。

A3,A4:读出source的完整字段,columns的计算结果为["A","B","C","D"]。

A5:动态生成MERGE语句。pks.(…)是循环函数,可对集合(包括结果集)的成员依次计算,计算中可用~引用循环变量,用#引用循环计数。

A6:执行MERGE语句。

由于表结构未知,用存储过程或JAVA获得表结构再动态拼出SQL非常麻烦。使用集合类计算支持良好的集算器来做,代码简单,脚本通用,易于维护。

集算脚本的计算结果可以作为报表数据源供报表使用,还可以在JAVA程序中通过JDBC的方式读取并使用,JAVA读取调用集算脚本代码如下:

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");

//调用集算器脚本(类似存储过程),其中p1是集算脚本的文件名

st =(com. esproc.jdbc.InternalCStatement)con.prepareCall("call p1()");

st.setObject(1,"table1");

st.setObject(2," table2");

//执行脚本

st.execute();

……

调用集算器脚本和访问数据库的方法完全一样,熟悉JDBC的程序员可以很快掌握。

关于集算器JDBC的部署和调用的更详细信息可参考集算器集成应用之被JAVA调用

动态表间连接

相对静态的表间连接,动态表间连接事先并不知道要使用的表。如下面的数据查询:

A表

B表

C表

现需要根据A表的TableName获取B表或C表对应ID的Num值。

目标结果:

实现脚本:

A1:执行SQL从A表取数;

A2:先按TableName分组,循环分组拼接动态查询语句,最后把查询结果按照ID排序。

通过集算器的集合计算能力(分组后仍然保存着分组成员供后续使用),让动态SQL的拼接工作简单化。

特殊格式数据更新

除了动态数据查询,有时还需要进行动态更新,更新的数据经常来源于第三方程序,其格式也多种多样,如JSON格式、XML等。在特殊的业务背景下,有时需要将这些较特殊格式(相对传统的二维表来说)的数据更新到(关系)数据库中。这就需要借助第三方程序完成,而像JAVA等高级语言存在缺少类库、硬编码困难等问题。这时可以采用集算器来完成,下面来看一个集算器解析JSON格式文件入库的例子,源数据如下:

要求:将上述内容中指定节点,主要是imei的Service列表更新到数据库2张表groups和Services中。

这里的JSON串由于包含多层且很多层都是动态的(如LIST和SERVICES下的节点数量和名称都不固定),这为解析带来了很大难度;而且其中属性名部分还包含空格(如MOVISTAR SPAIN)和点号(如Requires.Network)这也大大增加了解析难度,使用JAVA非常难写。

实现脚本:

A1:读入JSON格式文件,结果为带有层次的结果集;

A2-A3:创建存储更新内容的两个空序表;

A4-D10:循环A1,动态解析内容并将解析结果输出到A2、A3目标结果序表中;

A11-A12:执行更新,将A2、A3序表更新到groups和services表中。

http://datamachine.iteye.com/blog/2219100

Java下拼接执行动态SQL语句(转)的更多相关文章

  1. Java下拼接运行动态SQL语句

    mod=viewthread&tid=3039" target="_blank">Java拼接动态SQL的一般做法有       1.使用动态语句 非常多数 ...

  2. 使用Oracle的DBMS_SQL包执行动态SQL语句

    引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle ...

  3. 存储过程中执行动态Sql语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...

  4. 怎样SQL存储过程中执行动态SQL语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...

  5. 用sp_executesql执行动态SQL语句及获得返回值

    过去我执行拼凑出来的动态SQL语句,都直接使用EXEC @sql 的方式.有好几次,都看到有资料说,应该尽量使用 sp_executesql. 究其原因,是因为仅仅参数不同的情况下,sp_execut ...

  6. 自定义函数执行动态sql语句

    --函数中不能调用动态SQL,使用用存储过程吧.如果还要对函数做其他操作,换成存储过程不方便,可以考虑把其他操作一起封装在存储过程里面.如:   create proc [dbo].[FUN_YSCL ...

  7. MySQL存储过程中实现执行动态SQL语句

    sql语句中的任何部分都可以作为参数. DROP PROCEDURE if exists insertdata; delimiter //CREATE PROCEDURE insertdata(IN ...

  8. 动态sql语句

    当需要根据外部输入的参数来决定要执行的SQL语句时,常常需要动态来构造SQL查询语句,个人觉得用得比较多的地方就是执行搜索查询的SQL语句.对于搜索,可能要根据搜索条件判断来动态执行SQL语句. 在S ...

  9. java:Hibernate框架3(使用Myeclipse逆向工程生成实体和配置信息,hql语句各种查询(使用hibernate执行原生SQL语句,占位符和命名参数,封装Vo查询多个属性,聚合函数,链接查询,命名查询),Criteria)

    1.使用Myeclipse逆向工程生成实体和配置信息: 步骤1:配置MyEclipse Database Explorer: 步骤2:为项目添加hibernate的依赖: 此处打开后,点击next进入 ...

随机推荐

  1. Java---Condition控制线程通信

    java中控制线程通信的方法有:1.传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyAll()控制线程通信.不灵活. 2.利用Conditio ...

  2. P235 实战练习(集合类)

    将1~100之间的所有正整数存放在一个List集合中,并将集合中索引位置是10的对象从集合中移除. package org.hanqi.practise; import java.util.*; pu ...

  3. 【阿里云产品公测】阿里云ACE部署通用完整教程及评测

    [阿里云产品公测]阿里云ACE部署通用完整教程及评测 作者:阿里云用户bailimei ACE应该是目前在公测的服务中应用最广泛的一项服务.在公测云引擎ACE前曾使用过新浪SAE,而ACE给我的最初印 ...

  4. C# 绘制窗体客户非客户区要用WM_PAINT和WM_NCPAINT

    窗体分为两部分:客户区(Client area)和非客户区(Non-Client area) WM_PAINT消息.OnPaint()方法.GetDC()API函数都是处理窗体客户区绘制的   而标题 ...

  5. js中singleton模式解析及运用

    singleton模式,又名单例模式.顾名思义,就是只能实例化一次的类(javascript中没有真正的类,我们通常用函数来模拟类,习惯称之为"伪类").具体地说,singleto ...

  6. Python 改变当前工作目录

    在shell里编辑: import os os.getcwd()   #取得当前工作目录 os.chdir(r'目标目录')   # os.chdir(r'd:\learnpy')

  7. css如何使背景图片水平居中

    CSS中定位背景图片的属性是:background-position,用法background-position 属性设置背景图像的起始位置. 你要水平居中可以: div{background-pos ...

  8. Ubuntu安装中文输入法

    如果你没有因为各种尝试搞乱了Ubuntu系统的话: 1. 在All Settings 里找到 Language Support, Install/Remove Languages里安装Chinese ...

  9. 【我的漫漫跨考路】数据结构之单链表线性存储实现 Beta

    正文之前 昨天晚上阶段性的完成了一部分数学的复习,所以今天打算撸一撸代码,然后发现提电脑忘指针.所以自己磕磕盼盼,对照了一下网上的代码,总算把线性存储单链表的数据类型实现,给自己写出来了. 废话不多说 ...

  10. BAT级别分类

    阿里的级别:P为技术岗,M为管理岗.P7是技术专家级别. 阿里级别对应薪资:  百度使用的T系列及对应薪资: 腾讯的T系列及对应薪资: