• 【原创】6. 在MYSQL++中实现SQL语法中的NULL


    这次要说明的是在MYSQL++中为了实现SQL中的NULL而做出的一系列的举措。我的感觉是Null<T, B>类型通常出现在SSQLS和template Query中比较多。

    1. 什么是SQL语法中的NULL(以后简称SQL NULL,区别于C++ NULL)

    我们可以像下面这样创建一张表

    CREATE  TABLE tbl1  ( 
            id       INT       NOT NULL, 
            name     CHAR(20)          ,
            time     TIMESTAMP NULL );

    在MYSQL中,上述语句的创建出来的表的列的情况是(dbvisualize的截图),

    image

    也就是说,如果我们不指定NOT NULL,默认的就是NULL。

    再来看一下插入数据

    insert into  tbl1(id, time) values( 2, NOW() );

    这里没有指定可以为NULL的name的值,那么结果是怎样的?

    image

    那么是否可以通过一句update语句来重置上面漏掉的、已经为NULL的name?完全可以。update tbl1 set name = ‘hello world’ where id = 2;

    也就是说,SQL中的NULL并不是我们通常看到的字符串“”,而是一种状态,表示“空”。

    MYSQL++文档里说是,SQL null is equal to nothing else. SQL null exists when every value for a particular column is legal and you need something that means "no legal value".)。

    最后提一句,如果我们希望显式地往数据库中插入一个null,那么应该使用语句

    insert into  tbl1(id, name, time) values( 2, null, NOW() );

    2. MYSQL++中模拟SQL NULL的类型

    在MYSQL++中模拟SQL NULL的只有两个文件,分别是null.h和null.cpp。

    • null.cpp

    其中在null.cpp中只定义了如下一行代码

    const std::string null_str("NULL");
     
    • null.h

    在null.h中主要定了两个主类型(分别是null_type和Null<type, Bahavior>)以及三个工具类型(NullIsNull, NullIsZero, NullIsBlank)1. null_type这个类型无比简单

    image
     

    确实!什么都没有,除了一个让编译器为隐式类型转换报错的protected方法。也就是说,如下的代码是不被认可的。

    // 说明:
    // 1. mysqlpp::Null<T, Bahavior=NullIsNull> 的确是有一个构造函数只接受一个null_type的
    // 2. mysqlpp:::null 在null.h中被定义成一个const null_type null = null_type();
    
    int foo = return_some_value_for_foo();
    mysqlpp::Null<int> bar = foo ? foo : mysqlpp::null;
     

    在上述例子中,如果foo == 0,那么编译器就会执行foo = mysqlpp::null,也就是执行了protected方法mysqlpp::null.operator int(),所以编译器就报错了(因为引用了一个protected方法)另外,在null.h中,还定义了一个mysqlpp::null,我估计这个定义完全就是为了让客户端代码不经意间就用上了mysqlpp::null,例如,Null<int> foo = null;这里的null将会被编译器理解为mysqlpp::null。

     
     

    2. 三个工具类型

    这三个工具类型提供了类似的方法,不多说了,比较好理解。他们将会成为表示可以供Null的column的数据类型的对于NULL的解释的任务。
    image
    image
    image
     
     

    3. Null<Type, Bahavior = NullIsNull>类型该类型是表示一个可以为SQL NULL的column的数据的数据类型。其实它的含义就是“可以保存真实数据或者SQL NULL”的数据结构。例如对于有如下的表格

    CREATE  TABLE tbl1  ( 
            id       INT       NOT NULL, 
            name     CHAR(20)          ,
            num      SMALLINT  NULL );

    对于name列,就可以在C++代码中使用Null<sql_char>表示,对于num列,就可以用Null<sql_smallint>表示。说明(取自sql_types.h)

    typedef int16_t                    sql_smallint;
    typedef std::string                sql_char;
     

    MYSQL++的作者一再强调,Null<T,B>类型是一个“holds data that can be null”的类型,也就是说,他真正模仿了SQL NULL。例如,对于上述的name列,我们可以对他赋值为null,也可以赋值为某个字符串。同样,这里的Null<T, B>类型就可以有这个功能,

    It can hold a non-null value, you can then assign null to it (using MySQL++'s global mysqlpp::null object), and then assign a regular value to it again

    • 成员变量

    该类型其实只有两个成员变量,

    1. Type data;

    这里的Type就是Null<T, B>中的T,例如如果是Null<sql_char>,那么这个Type就是sql_char。它表示的是如果该列非Null(即,该列是一个真实的值)时的值。

    2. bool is_null;

    这个bool型就表示这个Null<T,B>是否表示的SQL NULL。如果是SQL NULL则上述的data成员变量也变得无效了,而is_null也就成为true。

    • 成员函数

    这里的成员函数可以大致被分成以下几组

    1. 构造函数与赋值函数

    image

    image

    注意这里的Type表示的Null<T, B>中的T。

    image

    从这里我就发现了为什么要定义这个null_type了,可能就是为了这里的构造起来方便(上文中已经有过交代了)

    image

    2. 类型转换函数

    image

    注意这里的Behavior指的是Null<T, B>中的B,而这个默认的B就是NullIsNull结构体,在构造Null<T, B>的时候,我们可以指定这个行为。

    该函数就是为了如下形式的代码而创建的

    Null<sql_char, NullIsBlank> name("abc");
    sql_char what_is_the_name = name; // what_is_the_name = "abc"
    
    name = mysqlpp::null;
    sql_char what_is_the_name = name; 

    // what_is_the_name = ""

    3. 比较函数

    这里定义了一系列的比较操作,比如oprator ==, operator !=, operator <, operator >等。基本的法则是

    1) Two null objects are equal to each other, and null is less than not-null

    2) Two null objects are equal, and null is not equal to not-null. If neither is null, we delegate to operator ==

     
  • 相关阅读:
    记第一场cf比赛(Codeforces915)
    Uva11468:Substring
    Uva11732:"strcmp()" Anyone?
    Uva1014:Remember the Word
    洛谷P2502:[HAOI2006]旅行
    bzoj3677: [Apio2014]连珠线
    bzoj4906: [BeiJing2017]喷式水战改
    海上孤独的帆
    Treap基本用法总结
    noip2017考前基础复习——数论数学
  • 原文地址:https://www.cnblogs.com/aicro/p/3633504.html
Copyright © 2020-2023  润新知