Clickhosue与MySQL语法差异

以下是 ClickHouse 与 MySQL 语法的一些不同之处:

1. 数据类型

ClickHouse 支持比 MySQL 更多的数据类型,在 ClickHouse 中,例如 Int8、Int16、Int32、UInt8、UInt16、UInt32、UInt64 这些数据类型都是可以使用的。此外,ClickHouse还支持更多的日期和时间格式。

2. SQL 语法

虽然 ClickHouse 和 MySQL 都支持 SQL 语法,但 ClickHouse 支持更多的 SQL 语法和函数。例如,ClickHouse 支持类似于 NoSQL 数据库的数组和嵌套数据结构,如 Array(T) 和 Tuple(A, B, C) 等类型。ClickHouse 还支持超时控制、数据分区,以及通过 `SAMPLE` 关键字可以对数据进行随机取样等操作。在 ClickHouse 中,可以用 `SELECT` 语句查询数据,与 MySQL 类似,但是 ClickHouse 的 `SELECT` 语句支持更多的聚合函数,如 `SUM`, `AVG`, `MEDIAN`, `STDDEV`, `TOPK`, `MIN`, `MAX`, `GROUP_CONCAT` 等。

3. 外部语言支持

ClickHouse 支持使用不同的编程语言与 ClickHouse 进行交互,如 Python、Java、C++、Go 等。而 MySQL 则依赖于各种不同的客户端程序库。

4. 索引

在索引上,ClickHouse 和 MySQL 也有所不同。ClickHouse 是一种列式存储数据库,索引通常依赖于排序,而 MySQL 的索引通常是基于 B-Tree 进行构建的。这里只是简单介绍了 ClickHouse 和 MySQL 语法的一些差异,具体的差异还可能包括具体的配置、性能特点、数据处理方式等等。

日期格式化的差异:

Clickhouse

在 ClickHouse中,日期格式化可以通过 `FORMATDateTime` 函数来实现,它的语法如下:

FORMATDateTime(date, format)

其中,`date` 为日期或日期时间类型的表达式,`format` 为日期格式化字符串。和 MySQL 不同的是,在 ClickHouse 中,日期格式化字符串采用 C++ 语言风格的格式化方式,具体的格式化字符可以参考 ClickHouse 官方文档中关于时间数据类型的说明。

以下是一些常见的格式化字符串示例:

- `%Y`: 年份,例如 `2021`
- `%y`: 年份的最后两位数,例如 `21`
- `%m`: 月份(01-12),例如 `02`
- `%d`: 日期(01-31),例如 `14`
- `%H`: 小时(00-23),例如 `15`
- `%M`: 分钟(00-59),例如 `17`
- `%S`: 秒(00-59),例如 `59`
- `%s`: 自纪元(1970 年 1 月 1 日)以来的秒数,例如 `1634234272`
- `%f`: 微秒,例如 `123456`
- `%v`: ISO 8601 格式年份和周数,例如 `2021-W41`
- `%W`: 一年中的周数,例如 `42`
- `%a`: 星期几的简写,例如 `Mon`
- `%A`: 星期几的全称,例如 `Monday`
- `%b`: 月份的简写,例如 `Jan`
- `%B`: 月份的全称,例如 `January`

以下是一个示例:

SELECT FORMATDateTime('2021-10-15 14:30:00', '%Y-%m-%d %H:%M:%S') AS formatted_date;

输出如下:
┌─formatted_date───────┐
│ 2021-10-15 14:30:00 │
└──────────────────────┘ 

需要注意的是,在使用 `FORMATDateTime` 函数时,如果日期或日期时间格式不合法会导致函数返回 NULL。

 MySQL

在 MySQL 中,日期格式化可以通过 `DATE_FORMAT` 函数来实现,它的语法如下:

DATE_FORMAT(date, format)

其中,`date` 为日期或日期时间类型的表达式,`format` 为日期格式化字符串。MySQL 使用与 C 语言中的 `strftime()` 函数类似的格式化方式,具体的格式化字符可以参考 MySQL 官方文档中有关日期和时间函数的说明。

以下是一些常见的格式化字符串示例:

- `%Y`: 年份(例如 `2021`)
- `%y`: 年份的最后两位数(例如 `21`)
- `%m`: 月份(01-12,例如 `02`)
- `%d`: 日期(01-31,例如 `14`)
- `%H`: 小时(00-23,例如 `15`)
- `%i`: 分钟(00-59,例如 `17`)
- `%s`: 秒(00-59,例如 `59`)
- `%W`: 星期几的全称(例如 `Sunday`)
- `%w`: 星期几的数字表示(0 表示周日,1 表示周一,依此类推)
- `%M`: 月份的全称(例如 `January`)
- `%b`: 月份的简写(例如 `Jan`)
- `%a`: 星期几的简写(例如 `Sun`)

以下是一个示例:

SELECT DATE_FORMAT('2021-10-15 14:30:00', '%Y-%m-%d %H:%i:%s') AS formatted_date;

输出如下:
+---------------------+
| formatted_date      |
+---------------------+
| 2021-10-15 14:30:00 |
+---------------------+

需要注意的是,在使用 `DATE_FORMAT` 函数时,如果日期或日期时间格式不合法会导致函数返回 NULL。另外,MySQL 也支持 `STR_TO_DATE()` 函数可以把字符串转换成日期或者日期时间类型的值,其语法如下:

STR_TO_DATE(dateString, format)

其中,`dateString` 为字符串类型的值,`format` 为日期或日期时间格式化字符串,与 `DATE_FORMAT()` 函数的格式化字符串基本相同。

小结

两个数据库中日期格式化所使用的函数不同,以及具体的格式化字符串不相同。

将日期或数值转换为字符串格式

MySQL语法:date_format函数

Oracle语法:to_char函数

Clickhouse语法:FORMATDateTime函数

案例:

 public static String dateToChar(String fieldName,String format){
        if (StringUtils.equalsIgnoreCase("mysql", Constant.DS_TYPE)){
            return "date_format("+fieldName+", '"+format+"')";
        }
        if (StringUtils.equalsIgnoreCase("oracle", Constant.DS_TYPE)){
            return "to_char("+fieldName+", '"+format+"')";
        }
        if (StringUtils.equalsIgnoreCase("clickhouse",Constant.DS_TYPE)) {
                return "FORMATDateTime(" + fieldName + ", '" + format + "')";
        }
        return "";
    }
//以上代码将使用FORMATDateTime函数将fieldName字段按照给定的format格式化为字符串。请注意,在ClickHouse中,日期和时间数据类型都可以直接转换为字符串,无需进行类型转换。

将字符串转换为日期类型

MySQL语法:str_to_date函数

Oracle语法:to_date函数

Clickhouse语法:toDateTime或者toDate函数

案例:

public static String charToDate(String fieldName,String format){
        if (StringUtils.equalsIgnoreCase("mysql", Constant.DS_TYPE)){
            return "str_to_date("+fieldName+",'"+format+"')";
        }
        if (StringUtils.equalsIgnoreCase("oracle", Constant.DS_TYPE)){
            return "to_date("+fieldName+",'"+format+"')";
        }
        if (StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)) {
            return "to" + (format.contains(":") ? "DateTime" : "Date") + "(" + fieldName + ", '" + format + "')";
        }
        return "";
    }
//以上代码将根据format参数是否包含时间信息,来确定使用toDateTime或者toDate函数进行转换。具体而言,如果format中包含冒号,则使用toDateTime函数;否则使用toDate函数。

//请注意,在ClickHouse中,日期和时间数据类型都可以直接从字符串中解析而来,无需进行类型转换。因此,我们可以直接使用toDateTime或toDate函数对字符串进行解析。

 在字段或表达式为空时返回指定的默认值-----------替换值

MySQL语法:IFNULL函数

Oracle语法:NVL函数

Clickhouse语法:IFNULL函数

案例:

if (StringUtils.equalsIgnoreCase("oracle", Constant.DS_TYPE)){
            if (value instanceof Integer){
                return "NVL(" + fieldName + "," + value + ")";
            }else {
                return "NVL(" + fieldName + ",'" + value+ "')";
            }
        }
if (StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)) { 
    if (value instanceof Integer) {
        return "ifNull(" + fieldName + ", " + value + ")";
    } else {
        return "ifNull(" + fieldName + ", '" + value + "')";
    }
}
// 以上代码会根据传入的参数类型,使用ifNull函数在字段或表达式为空时返回相应的默认值。如果value参数是整数类型,则直接将其作为默认值传递给ifNull函数;否则需要使用单引号将其作为字符串传递给ifNull函数。

注意:这里ck和mysql的语法是一样的!!!

在字段或表达式为空时返回指定的默认值---------替换字段名

(这里判断`fieldName`字段是否为空,如果为空,则返回`notNullFieldName`字段的值作为替代)

MySQL语法:IFNULL函数

Oracle语法:NVL函数Clickhouse语法:IFNULL函数

//对于Oracle中的NVL函数,在ClickHouse中可以使用IFNULL函数来代替。
//以下是代码示例:

if (StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)) {
    return "IFNULL(" + fieldName + "," + notNullFieldName + ")";
}
//以上代码使用IFNULL函数来判断fieldName字段是否为空,如果为空,则返回notNullFieldName字段的值作为替代。

删除表

MySQL语法:DROP TABLE IF EXISTS

Oracle语法:DROP TABLE

Clickhouse语法:DROP TABLE IF EXISTS

案例:
//在ClickHouse中,你可以使用DROP TABLE语句来删除表。下面是一个示例的函数表达式:

public String getDropTableExpression(String tableName) {
    if (StringUtils.equalsIgnoreCase("oracle", Constant.DS_TYPE)){
            return "DROP TABLE " + tableName;
        }
        if (StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)) {
            return "DROP TABLE IF EXISTS " + tableName;
        }
        return "";
}
//在以上代码中,tableName是要删除的表的名称。DROP TABLE语句可以用于删除指定名称的表,同时使用IF EXISTS避免在删除不存在的表时引发错误。

//请注意,在执行删除操作之前,请先确保你具有足够的权限,并且要谨慎操作以避免误删数据。

创建相似表

MySQL语法:CREATE TABLE ... LIKE函数

在 MySQL 中,创建表结构相同的新表可以使用以下几种方法:

1. 使用 `CREATE TABLE ... LIKE` 语句:这种方法允许你基于已存在的表创建一个具有相同结构的新表。示例如下:

CREATE TABLE new_table LIKE existing_table;

2.使用 `CREATE TABLE ... AS SELECT` 语句:这种方法可以从一个现有表复制表结构和数据创建新表。示例如下:

CREATE TABLE new_table AS SELECT * FROM existing_table WHERE 1 = 0;

上述示例中,`WHERE 1 = 0` 部分用于确保查询不返回任何数据,只复制表结构。

3. 使用 `CREATE TABLE ... SELECT` 语句:这种方法允许你从一个现有表选择特定的列和数据创建新表。示例如下:

CREATE TABLE new_table SELECT column1, column2 FROM existing_table WHERE condition;

上述示例中,你可以根据需要指定要复制的特定列,并通过指定条件来筛选要复制的数据。

需要注意的是,上述方法只会复制表的结构和数据,而不包括索引、约束、触发器等对象。如果需要完整复制表的结构,可以使用工具或脚本来执行此操作。

无论使用哪种方法,在创建新表之后,你还可以根据需要对新表进行修改,例如添加索引、约束等操作。

Oracle语法:CREATE TABLE ... AS函数或CREATE TABLE ... LIKE函数

在Oracle中,你可以使用`LIKE`关键字来创建一个与现有表相似的新表。以下是可能的示例代码:

CREATE TABLE new_table LIKE existing_table;

在以上代码中,`new_table`是要创建的新表的名称,`existing_table`是现有表的名称。使用`LIKE`关键字可以避免重新定义表结构,而是将现有表的结构复制到新表中。

请注意,使用`LIKE`关键字创建新表时,新表不会复制现有表中的数据。如果需要复制数据,请考虑使用INSERT INTO SELECT语句。

Clickhouse语法:CREATE TABLE ... AS函数

在 ClickHouse 中,创建表结构相同的表可以使用 `CREATE TABLE ... AS` 语句。该语句可以从一个现有表复制表结构并创建新表。

以下是使用 `CREATE TABLE ... AS` 语句创建表的示例:

CREATE TABLE new_table AS SELECT * FROM existing_table WHERE 1 = 0;

上述示例中,`existing_table` 是已存在的表,而 `new_table` 是要创建的新表。`SELECT * FROM existing_table WHERE 1 = 0` 部分是用来复制表结构但不复制数据的,因为 `WHERE 1 = 0` 总是评估为假,所以不会返回任何行。你也可以根据需要在 `SELECT` 子句中指定需要复制的列,例如:

CREATE TABLE new_table AS SELECT column1, column2 FROM existing_table WHERE 1 = 0;

上述示例中,只复制了 `existing_table` 中的 `column1` 和 `column2` 列。

需要注意的是,`CREATE TABLE ... AS` 语句仅用于创建表结构相同的新表,并不会复制索引、约束和其他表级属性。如果需要完整复制表的结构,包括索引和约束等,可以考虑使用工具或脚本进行复制操作。

另外,还可以通过 `CREATE TABLE ... LIKE` 语句创建表结构相同的新表,例如:

CREATE TABLE new_table (LIKE existing_table);

上述示例中,`new_table` 的表结构将与 `existing_table` 相同。

无论是使用 `CREATE TABLE ... AS` 还是 `CREATE TABLE ... LIKE`,在创建新表之后,你还可以根据需要对新表进行修改、添加索引等操作。

获取当前系统时间

MySQL语法:sysdate()函数

Oracle语法:sysdate函数

在Oracle中,你可以使用`SYSDATE`函数来获取当前系统时间,该函数返回的是一个`DATE`类型的值,表示当前日期和时间。

以下是一个使用示例:

SELECT SYSDATE FROM DUAL;
-- 输出:2019-12-27 11:42:15

在以上代码中,`DUAL`是Oracle中的一个虚拟表,可以用于测试或查询单个行的情况。使用`SYSDATE`函数从`DUAL`表中查询当前系统时间并将其返回。

Clickhouse语法:now()函数

//在ClickHouse中,你可以使用now()函数来获取当前系统时间,用于替换MySQL中的sysdate()函数。以下是可能的代码示例:
if (StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)){
    return "now()";
}
//以上代码会在ClickHouse中将now()函数作为替代返回。
//注意,在使用不同数据库之间进行迁移时,需要注意一些函数和语法的兼容性问题,以保证代码和查询的正确性。

日期格式化

// mysql
String format = null;
        if (StringUtils.equalsIgnoreCase("mysql", dsType)) {
            if (dateFormat.equals("yyyy") || dateFormat.equals("1")) {
                format = "%Y";
            } else if (dateFormat.equals("yyyyMM") || dateFormat.equals("2")) {
                format = "%Y%m";
            } else if (dateFormat.equals("yyyyMMdd") || dateFormat.equals("3")) {
                format = "%Y%m%d";
            } else if (dateFormat.equals("yyyy-MM-dd")) {
                format = "%Y-%m-%d";
            } else if (dateFormat.equals("yyyy-MM-dd hh:mi:ss")) {
                format = "%Y-%m-%d %H:%i:%s";
            } else if (dateFormat.equals("yyyyMMdd hh:mi:ss")) {
                format = "%Y%m%d %H:%i:%s";
            } else if (dateFormat.equals("yyyy/MM/dd hh:mi:ss")) {
                format = "%Y/%m/%d %H:%i:%s";
            } else if (dateFormat.equals("yyyy/MM/dd")) {
                format = "%Y/%m/%d";
            } else if (dateFormat.equals("yyyy.MM.dd")) {
                format = "%Y.%m.%d";
            } else if (dateFormat.equals("yyyy.MM.dd hh:mi:ss")) {
                format = "%Y.%m.%d %H:%i:%s";
            } else {
                format = "%Y-%m-%d";
            }
// clickhouse 
if (StringUtils.equalsIgnoreCase("clickhouse", dsType)) {
    if (dateFormat.equals("yyyy") || dateFormat.equals("1")) {
        format = "YYYY";
    } else if (dateFormat.equals("yyyyMM") || dateFormat.equals("2")) {
        format = "YYYYMM";
    } else if (dateFormat.equals("yyyyMMdd") || dateFormat.equals("3")) {
        format = "YYYYMMdd";
    } else if (dateFormat.equals("yyyy-MM-dd")) {
        format = "YYYY-MM-dd";
    } else if (dateFormat.equals("yyyy-MM-dd hh:mi:ss")) {
        format = "YYYY-MM-dd HH:mm:ss";
    } else if (dateFormat.equals("yyyyMMdd hh:mi:ss")) {
        format = "YYYYMMdd HH:mm:ss";
    } else if (dateFormat.equals("yyyy/MM/dd hh:mi:ss")) {
        format = "YYYY/MM/dd HH:mm:ss";
    } else if (dateFormat.equals("yyyy/MM/dd")) {
        format = "YYYY/MM/dd";
    } else if (dateFormat.equals("yyyy.MM.dd")) {
        format = "YYYY.MM.dd";
    } else if (dateFormat.equals("yyyy.MM.dd hh:mi:ss")) {
        format = "YYYY.MM.dd HH:mm:ss";
    } else {
        format = "YYYY-MM-dd";
    }
}
// 在以上代码中,我将日期格式占位符%Y替换为ClickHouse中的对应格式,例如将%Y替换为YYYY。

// 请注意,这只是将日期格式字符串转换为ClickHouse所需的格式,稍后你可能需要将该日期格式应用于实际的查询或操作。

构建连接符

MySQL语法:

StringBuilderstringBuilder=newStringBuilder();
if(StringUtils.equalsIgnoreCase("mysql",Constant.DS_TYPE)){
for(inti=0;i<fieldName.length;i++){
stringBuilder.append(fieldName[i]);
if(i!=fieldName.length-1){
stringBuilder.append(",");
}else{
stringBuilder.append(")");
}
}
stringBuilder.insert(0,"CONCAT(");
}

Oracle语法:

StringBuilderstringBuilder=newStringBuilder();
if(StringUtils.equalsIgnoreCase("oracle",Constant.DS_TYPE)){
for(inti=0;i<fieldName.length;i++){
stringBuilder.append(fieldName[i]);
if(i!=fieldName.length-1){
stringBuilder.append("||");
}
}
}

Clickhouse语法:

1.ClickHouse不支持CONCAT函数。可以使用字符串连接运算符来替代。将stringBuilder.insert(0,"CONCAT(");修改为stringBuilder.insert(0, "(")。

2.ClickHouse的字符串连接运算符是||,而不是MySQL中的逗号(,)。将stringBuilder.append(",");修改为stringBuilder.append(" || ");。

修改后的代码如下所示:

StringBuilderstringBuilder=newStringBuilder();
if(StringUtils.equalsIgnoreCase("clickhouse", Constant.DS_TYPE)) {
    for(inti=0; i < fieldName.length; i++) {
        stringBuilder.append(fieldName[i]);
        if(i != fieldName.length - 1) {
            stringBuilder.append(" || ");
        } else{
            stringBuilder.append(")");
        }
    }
    stringBuilder.insert(0, "(");
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值