C#实现定义一套中间SQL可以跨库执行的SQL语句(案例详解)

目录
  • hisql查询样例
    • 单表查询
  • group by查询
    • having 查询
    • join 多表查询
    • 分页
  • hisql 实现参数化
  • 链式查询
  • hisql语句和链式查询混用

目前数据的种类非常多,每种数据都支持sql语句,但是大家发现没有每种数据的SQL都有自己的语法特性,都是SQL语句都没有一个特定的语法标准,导致开发人员在开发的过程中无法任意选库(如果用自己不熟的库都会要学习一遍SQL语法),主要是学习成本太高

那么有没有一种工具能够统一下sql语法规则,只要学一种sql语句就可以跨库执行,让开发人员不用学习每种库的SQL语句呢?

下面就给大家介绍一款开源工具hisql源码 hisql介绍

hisql查询样例

单表查询

根据hisql语句通过ToSql()方法生成目标sql的原生sql

var _sql = sqlClient.HiSql("select * from HTest01 where  CreateTime>='2022-02-17 09:27:50' and CreateTime<='2022-03-22 09:27:50'").ToSql();

hisql生成的sqlserver 的sql 如下的所示

select  [htest01].[SID],[htest01].[UName],[htest01].[Age],[htest01].[Salary],[htest01].[Descript],[htest01].[CreateTime],[htest01].[CreateName],[htest01].[ModiTime],[htest01].[ModiName] from [HTest01] as [HTest01]
 where [htest01].[CreateTime] >= '2022-02-17 09:27:50.000' and [htest01].[CreateTime] <= '2022-03-22 09:27:50.000'

hisql生成mysql的sql如下所示

select   `htest01`.`SID`,`htest01`.`UName`,`htest01`.`Age`,`htest01`.`Salary`,`htest01`.`Descript`,`htest01`.`CreateTime`,`htest01`.`CreateName`,`htest01`.`ModiTime`,`htest01`.`ModiName` from `htest01` as `htest01`
 where `htest01`.`CreateTime` >= '2022-02-17 09:27:50.000' and `htest01`.`CreateTime` <= '2022-03-22 09:27:50.000'

hisql生成postgresql 的sql下所示

select  "htest01"."SID","htest01"."UName","htest01"."Age","htest01"."Salary","htest01"."Descript","htest01"."CreateTime","htest01"."CreateName","htest01"."ModiTime","htest01"."ModiName" from "HTest01" as "htest01"
 where "htest01"."CreateTime" >= '2022-02-17 09:27:50.000' and "htest01"."CreateTime" <= '2022-03-22 09:27:50.000'

大家可以会问 明明是 "select * from HTest01 where CreateTime>='2022-02-17 09:27:50' and CreateTime<='2022-03-22 09:27:50'" 用的 * 查询 生成的sql语句为什么会直接列出所有字段呢? 熟HiSql的网友都应该知道这里其实隐藏了一个功能就是用户可以自定义字段排序在系统表 Hi_FieldModel 中可配置

group by查询

hisql 默认支持的常用函数 max , count , min , sum , avg

string sql = sqlClient.HiSql("select FieldName, count(FieldName) as NAME_count,max(FieldType) as FieldType_max from Hi_FieldModel  group by FieldName").ToSql();

hisql生成的sqlserver 的sql 如下的所示

select  [hi_fieldmodel].[FieldName],count(*) as NAME_count,max([hi_fieldmodel].[FieldType]) as FieldType_max from [Hi_FieldModel] as [Hi_FieldModel]
 group by [hi_fieldmodel].[FieldName]

hisql生成mysql的sql如下所示

select   `hi_fieldmodel`.`FieldName`,count(*) as NAME_count,max(`hi_fieldmodel`.`FieldType`) as FieldType_max from `Hi_FieldModel` as `hi_fieldmodel`
 group by `hi_fieldmodel`.`FieldName`

hisql生成postgresql 的sql下所示

select  "hi_fieldmodel"."FieldName",count(*) as NAME_count,max("hi_fieldmodel"."FieldType") as FieldType_max from "Hi_FieldModel" as "hi_fieldmodel"
 group by "hi_fieldmodel"."FieldName"

having 查询

上次有网友说having 实现起来很麻烦通过正则表达式解析很难实现,我只能说很多网友对正则表达式的理解还不是很深,正则表达式已经应用于种类型的编译器中,下面就来演示一下Having

string sql_having = sqlClient.HiSql("select FieldName, count(FieldName) as NAME_count,max(FieldType) as FieldType_max from Hi_FieldModel  group by FieldName having count(FieldName) > 1").ToSql();

hisql生成的sqlserver 的sql 如下的所示

select  [hi_fieldmodel].[FieldName],count(*) as NAME_count,max([hi_fieldmodel].[FieldType]) as FieldType_max from [Hi_FieldModel] as [Hi_FieldModel]
 group by [hi_fieldmodel].[FieldName]
 having count(*) > 1

hisql生成mysql的sql如下所示

select   `hi_fieldmodel`.`FieldName`,count(*) as NAME_count,max(`hi_fieldmodel`.`FieldType`) as FieldType_max from `Hi_FieldModel` as `hi_fieldmodel`
 group by `hi_fieldmodel`.`FieldName`
 having count(*) > 1

hisql生成postgresql 的sql下所示

select  "hi_fieldmodel"."FieldName",count(*) as NAME_count,max("hi_fieldmodel"."FieldType") as FieldType_max from "Hi_FieldModel" as "hi_fieldmodel"
 group by "hi_fieldmodel"."FieldName"
 having count(*) > 1

join 多表查询

hisql inner join 和 in 操作语法

var sql = sqlClient.HiSql("select a.tabname from hi_fieldmodel as a inner join Hi_TabModel as  b on a.tabname =b.tabname inner join Hi_TabModel as c on a.tabname=c.tabname where a.tabname='h_test'  and a.FieldType in (11,41,21)  ").ToSql();

hisql生成的sqlserver 的sql 如下的所示

select  [a].[TabName] from [Hi_FieldModel] as [a]
  inner join [Hi_TabModel] as [b] on [a].[TabName] = [b].[TabName] inner join [Hi_TabModel] as [c] on [a].[TabName] = [c].[TabName]
 where [a].[TabName] = 'h_test' and [a].[FieldType] in (11,41,21)

hisql生成mysql的sql如下所示

select   `a`.`TabName` from `Hi_FieldModel` as `a`
  inner join `Hi_TabModel` as `b` on `a`.`TabName` = `b`.`TabName` inner join `Hi_TabModel` as `c` on `a`.`TabName` = `c`.`TabName`
 where `a`.`TabName` = 'h_test' and `a`.`FieldType` in (11,41,21)

hisql生成postgresql 的sql下所示

select  "a"."TabName" from "Hi_FieldModel" as "a"
  inner join "Hi_TabModel" as "b" on "a"."TabName" = "b"."TabName" inner join "Hi_TabModel" as "c" on "a"."TabName" = "c"."TabName"
 where "a"."TabName" = 'h_test' and "a"."FieldType" in (11,41,21)

分页

hisql 分页 只要在日常查询上增加 Take() 每页显示多少数据 Skip() 显示第几页

var sql = sqlClient.HiSql("select a.tabname from hi_fieldmodel as a inner join Hi_TabModel as  b on a.tabname =b.tabname inner join Hi_TabModel as c on a.tabname=c.tabname where a.tabname='h_test'  and a.FieldType in (11,41,21)  ").Take(2).Skip(2).ToSql();

hisql生成的sqlserver 的sql 如下的所示

select  [TabName] from (
select ROW_NUMBER() OVER(Order by [a].[FieldType] ASC) AS _hi_rownum_, [a].[TabName] from [Hi_FieldModel] as [a]
  inner join [Hi_TabModel] as [b] on [a].[TabName] = [b].[TabName] inner join [Hi_TabModel] as [c] on [a].[TabName] = [c].[TabName]
 where [a].[TabName] = 'h_test' and [a].[FieldType] in (11,41,21)
) as hi_sql
where hi_sql._hi_rownum_ BETWEEN (2-1)*2+1 and 2*2 order by  _hi_rownum_ asc

hisql生成mysql的sql如下所示

select `TabName` from (
select ROW_NUMBER() OVER(Order by `a`.`FieldType` ASC) AS `_hi_rownum_`, `a`.`TabName` from `Hi_FieldModel` as `a`
  inner join `Hi_TabModel` as `b` on `a`.`TabName` = `b`.`TabName` inner join `Hi_TabModel` as `c` on `a`.`TabName` = `c`.`TabName`
 where `a`.`TabName` = 'h_test' and `a`.`FieldType` in (11,41,21)
) as hi_sql
 order by  `_hi_rownum_` asc
limit 2,2

hisql生成postgresql 的sql下所示

select "TabName" from (
select ROW_NUMBER() OVER(Order by "a"."FieldType" ASC) AS "_hi_rownum_", "a"."TabName" from "Hi_FieldModel" as "a"
  inner join "Hi_TabModel" as "b" on "a"."TabName" = "b"."TabName" inner join "Hi_TabModel" as "c" on "a"."TabName" = "c"."TabName"
 where "a"."TabName" = 'h_test' and "a"."FieldType" in (11,41,21)
) as hi_sql
 order by  "_hi_rownum_" asc
limit 2 OFFSET 2

hisql 实现参数化

参数化可以有效的防注入,通过前端可以拼接的hisql语句通过参数化的方式传入, 这样就解决了注入问题

string sql1= sqlClient.HiSql("select * from hi_tabmodel where tabname=@tabname ", new { TabName="H_test" ,FieldName="DID"}).ToSql();
    string sql2= sqlClient.HiSql("select * from hi_tabmodel where tabname=@tabname or TabType in( @TabType)", new { TabName="H_test" , TabType =new List<int> { 1,2,3,4} }).ToSql();
    string sql3 = sqlClient.HiSql("select * from hi_tabmodel where tabname=@tabname ", new Dictionary<string, object> { { "TabName", "H_test" } }).ToSql();

链式查询

hisql除了提供hisql语法外还提供链式查询方法如下所示

string sql = sqlClient.Query("Hi_FieldModel").As("A").Field("A.FieldType")
                .Join("Hi_TabModel").As("B").On(new HiSql.JoinOn() { { "A.TabName", "B.TabName" } })
                .Where("A.TabName='GD_UniqueCodeInfo'").Group(new GroupBy { { "A.FieldType" } })
                .Sort("A.FieldType asc", "A.TabName asc")
                .Take(2).Skip(2)
                .ToSql();

hisql语句和链式查询混用

string sql = sqlClient.HiSql("select A.FieldType from Hi_FieldModel as A ")
                .Where("A.TabName='GD_UniqueCodeInfo'").Group(new GroupBy { { "A.FieldType" } })
                .Sort("A.FieldType asc", "A.TabName asc")
                .Take(2).Skip(2)
                .ToSql();

到此这篇关于C#实现定义一套中间SQL可以跨库执行的SQL语句的文章就介绍到这了,更多相关C#跨库执行SQL语句内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c#实现用SQL池,多线程定时批量执行SQL语句的方法

    在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发Socket通信服务的时候,网络传输很快,但是一旦加上数据库操作,性能一落千丈,数据库操作的效率往往成为一个系统整体性能的瓶颈.面对这问题,我们怎么办呢?好,下面我就为大家介绍一种方法:构建SQL池,分离业务逻辑层和数据访问层,让业务逻辑层从低效的数据库操作解脱,以提高系统整体性能. (一)SQL池 SQL池是SQL容器,用于存放业务逻辑层抛过来的SQL语句.SQL池主要提供以下几种方法: 1)internal string Pop()

  • C#中验证sql语句是否正确(不执行语句)

    SET PARSEONLY检查每个 Transact-SQL 语句的语法并返回任何错误消息,但不编译和执行语句.SET PARSEONLY { ON | OFF }当 SET PARSEONLY 为 ON 时,SQL Server 只分析语句.当 SET PARSEONLY 为 OFF 时,SQL Server 编译并执行语句.SET PARSEONLY 的设置是在分析时设置,而不是在执行或运行时设置.在存储过程或触发器中不要使用 PARSEONLY.如果 OFFSETS 选项为 ON 而且没有

  • C#中实现一次执行多条带GO的sql语句实例

    本文实例讲述了C#中实现一次执行多条带GO的sql语句.分享给大家供大家参考.具体如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Text.RegularExpressions; using System.Data.SqlClient; namespace ConsoleApplicati

  • C#实现连接SQL Server2012数据库并执行SQL语句的方法

    本文实例讲述了C#实现连接SQL Server2012数据库并执行SQL语句的方法.分享给大家供大家参考,具体如下: 开发工具:Visual Studio 2012 数据库: SQL Server 2012 使用Visual Studio时还是直接和微软自家的SQL Server数据库连接比较方便,就像使用Eclipse时和MySQL连接便捷一样的道理 无论使用什么工具步骤都一样: 1. 首先保证相关工具都已经正确安装了 2. 开启数据库连接服务 3. 在开发工具中通过用户名和口令与数据库进行关

  • C#实现定义一套中间SQL可以跨库执行的SQL语句(案例详解)

    目录 hisql查询样例 单表查询 group by查询 having 查询 join 多表查询 分页 hisql 实现参数化 链式查询 hisql语句和链式查询混用 目前数据的种类非常多,每种数据都支持sql语句,但是大家发现没有每种数据的SQL都有自己的语法特性,都是SQL语句都没有一个特定的语法标准,导致开发人员在开发的过程中无法任意选库(如果用自己不熟的库都会要学习一遍SQL语法),主要是学习成本太高 那么有没有一种工具能够统一下sql语法规则,只要学一种sql语句就可以跨库执行,让开发

  • oracle跨库查询dblink的用法实例详解

    本文实例讲述了oracle跨库查询dblink的用法.分享给大家供大家参考,具体如下: 1.创建之前的工作 在创建dblink之前,首先要查看用户是否有相应的权限.针对特定的用户,使用 sqlplus user/pwd登录后,执行如下语句: 复制代码 代码如下: select * from user_sys_privs t where t.privilege like upper('%link%'); 在sys用户下,显示结果为: SYS CREATE DATABASE LINK NO SYS

  • SQL Server 跨库同步数据

    最近有个需求是要跨库进行数据同步,两个数据库分布在两台物理计算机上,自动定期同步可以通过SQL Server代理作业来实现,但是前提是需要编写一个存储过程来实现同步逻辑处理.这里的存储过程用的不是opendatasource,而是用的链接服务器来实现的.存储过程创建在IP1:192.168.0.3服务器上,需要将视图v_custom的客户信息同步到IP2:192.168.0.10服务器上的t_custom表中.逻辑是如果不存在则插入,存在则更新字段. create PROCEDURE [dbo]

  • SQL Server 树形表非循环递归查询的实例详解

    很多人可能想要查询整个树形表关联的内容都会通过循环递归来查...事实上在微软在SQL2005或以上版本就能用别的语法进行查询,下面是示例. --通过子节点查询父节点 WITH TREE AS( SELECT * FROM Areas WHERE id = 6 -- 要查询的子 id UNION ALL SELECT Areas.* FROM Areas, TREE WHERE TREE.PId = Areas.Id ) SELECT Area FROM TREE --通过父节点查询子节点 WIT

  • jQuery 跨域访问解决原理案例详解

    浏览器端跨域访问一直是个问题,多数研发人员对待js的态度都是好了伤疤忘了疼,所以病发的时候,时不时地都要疼上一疼.记得很久以前使用iframe 加script domain 声明.yahoo js util 的方式解决二级域名跨域访问的问题. 时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了.好在,有jQuery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了跨域问题...有必要记下来备忘, 跨域的安全限制都是指浏览

  • oracle sql语言模糊查询--通配符like的使用教程详解

    oracle在Where子句中,可以对datetime.char.varchar字段类型的列用Like子句配合通配符选取那些"很像..."的数据记录,以下是可使用的通配符: %   零或者多个字符 _    单一任何字符(下划线) \     特殊字符 oracle10g以上支持正则表达式的函数主要有下面四个: 1,REGEXP_LIKE :与LIKE的功能相似 2,REGEXP_INSTR :与INSTR的功能相似 3,REGEXP_SUBSTR :与SUBSTR的功能相似 4,RE

  • SQL的各种连接Join案例详解

    最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN).SQL LEFT JOIN.SQL RIGHT JOIN.SQL FULL JOIN,其中前一种是内连接,后三种是外链接. 假设我们有两张表,Table A是上边的表,Table B是下边的表. Table A id name 1 Google 2 淘宝 3 微博 4 Facebook Table B id address 1 美国 5 中国 3 中国 6 美国 一.INNER JOIN 内连接是最常见的一种连接,只连接

  • SQL IDENTITY_INSERT作用案例详解

    一般情况下,当数据表中,莫一列被设置成了标识列之后,是无法向标识列中手动的去插入标识列的显示值.但是,可以通过设置SET IDENTITY_INSERT属性来实现对标识列中显示值的手动插入. 写法: SET IDENTITY_INSERT 表名 ON :表示开启对标识列显示值插入模式,允许对标识列显示值进行手动插入数据. SET IDENTITY_INSERT 表名 OFF:表示关闭对标识列显示值的插入操作,标识列不允许手动插入显示值. 注意:IDENTITY_INSERT的开启ON和关闭OFF

  • SQL之patindex函数的用法案例详解

    语法格式:PATINDEX ( '%pattern%' , expression ) 返回pattern字符串在表达式expression里第一次出现的位置,起始值从1开始算. pattern字符串在expression表达式里没找就返回0,对所有有效的文本和字符串就是有效的数据类型. 描述一下此函数的具体用法: 1. PATINDEX ( '%pattern%' , expression ) '%pattern%'的用法类似于 like '%pattern%'的用法,也就是模糊查找其patte

  • sql ROW_NUMBER()与OVER()方法案例详解

    语法格式:row_number() over(partition by 分组列 order by 排序列 desc) row_number() over()分组排序功能: 在使用 row_number() over()函数时候,over()里头的分组以及排序的执行晚于 where .group by.  order by 的执行. 例一: 表数据: create table TEST_ROW_NUMBER_OVER( id varchar(10) not null, name varchar(1

随机推荐