JAVA后台开发_从入门到精通

15 SQL语句技巧

2017-12-28  本文已影响10人  笑Skr人啊
    解决: 在group by 后面增加 order by null 就可以防止排序.
    select * from dept, emp where dept.deptno=emp.deptno; [简单处理方式,不推荐使用]

    select * from dept left join emp on dept.deptno=emp.deptno;  [左外连接,更ok!]
    select id from t where num is null  

    最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.  
    备注、描述、评论之类的可以设置为 NULL,其他的,最好不要使用NULL。

    不要以为 NULL 不需要空间,比如:char(100) 型,在字段建立时,空间就固定了, 
    不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,

    如果是varchar这样的变长字段, null 不占用空间。  

    可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:  
        select id from t where num = 0
    select id from t where num=10 or Name = 'admin'  

    可以这样查询:  
        select id from t where num = 10 
        union all 
        select id from t where Name = 'admin'
    select id from t where num in(1,2,3)

    对于连续的数值,能用 between 就不要用 in 了:
        select id from t where num between 1 and 3

    很多时候用 exists 代替 in 是一个好的选择:
        select num from a where num in(select num from b)

    用下面的语句替换:
        select num from a where exists(select 1 from b where num=a.num)

    因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;
    它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,
    因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
        select id from t where num = @num

    可以改为强制查询使用索引:
        select id from t with(index(索引名)) where num = @num

    应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
        select id from t where num/2 = 100

    应改为:
        select id from t where num = 100*2

    select id from t where substring(name,1,3) = 'abc'       --name以abc开头的id
    select id from t where datediff(day,createdate,'2005-11-30') = 0   --'2005-11-30'    --生成的id
    应改为:
    select id from t where name like 'abc%'
    select id from t where createdate >= '2005-11-30' and createdate < '2005-12-1'

    select col1,col2 into t from t where 1=0

    这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
        create table t(…)
    实际案例分析:拆分大的 DELETE 或INSERT 语句,批量提交SQL语句

        如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止相应。
        因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。

        Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,
        线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。

        如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,
        数据库链接,打开的文件数,可能不仅仅会让你的WEB服务崩溃,还可能会让你的整台服务器马上挂了。

        所以,如果你有一个大的处理,你一定把其拆分,使用 LIMIT oracle(rownum),sqlserver(top)条件是一个好的方法。
        下面是一个mysql示例:
            while(1){
                //每次只做1000条
                mysql_query(“delete from logs where log_date <= ’2012-11-01’ limit 1000”);

                if(mysql_affected_rows() == 0){
                    //删除完成,退出!
                    break;
                }

                //每次暂停一段时间,释放表让其他进程/线程访问。
                usleep(50000)
            }
上一篇 下一篇

猜你喜欢

热点阅读