Content Table

MySQL 数据类型

MySQL 中定义数据字段的类型对你数据库的优化是非常重要的,支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

数值类型

MySQL支持所有标准 SQL 数值数据类型,这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC),以及近似数值数据类型(FLOAT、REAL 和 DOUBLE)。

关键字 INT 是 INTEGER 的同义词,关键字 DEC 是 DECIMAL 的同义词。
BIT 数据类型保存位字段值,并且支持 MyISAM、MEMORY、InnoDB 和 BDB 表。
作为 SQL 标准的扩展,MySQL 也支持整数类型 TINYINT、MEDIUMINT 和 BIGINT。

Windows 设置 JDK 的默认编码

现在 Java 开发项目编码一般都是 UTF-8,Windows 下 JDK 的默认编码是 GB2312,可把其默认值设置为 UTF-8:

  1. 右键点击计算机 > 属性 > 高级系统设置 > 高级 > 环境变量 > 系统变量: 设置 JAVA_TOOL_OPTIONS 的值为 -Dfile.encoding=UTF-8
  2. 命令行显示 UTF-8 字符: 执行 chcp 65001,设置命令行的属性,选择字体 Lucida Console(不要选择点阵字体)。如果要换回 GBK 执行 chcp 936 ,再把字体改成点阵字体即可。

SQL Server 导出 CSV 和 XML

导出 XML

1
bcp "select * from tableName FOR XML AUTO, ROOT('Root')" queryout C:/x.xml -S(local) -T -r -c
  • -w: 使用 UTF-16 编码,小端
  • -c: 使用 GBK 编码
  • -c -C6501: 使用 UTF-8 编码,但是有的计算机上不支持
  • -T: 本机使用 -T 表示可信连接,如果是访问其他机器使用 -U user -P pwd 输入用户名和密码

注意:

  • 如果不使用 -r,则导出的 XML 每行最多有 2033 个字符,会破坏 XML,用了 -r 后就没有换行符了,整个 XML 的内容在同一行。
  • 内容中的 & 等特殊字符不会被转义就直接放到属性值里了,此时用 XML 库解析会出错。

导出 CSV

1
sqlcmd -S localhost -d dbName -E -o "csvFile.csv" -Q "set nocount on; select * from tableName" -W -w 999 -s ","
  • -W: remove trailing spaces from each individual field
  • -s",": sets the column seperator to the comma (,)
  • -w 999: sets the row width to 999 chars(this will need to be as wide as the longest row or it will wrap to the next line)
  • -U: username
  • -P: password
  • -h-1: removes column name headers from the result
  • set nocount on: 输出时不显示 XXX 行受到影响的统计信息

注意:sqlcmd 导出为 CSV 文件时,如果列中有逗号,那么导出的 CSV 文件会被破坏,还没找到好办法。

参考 How to export data as CSV format from SQL Server using sqlcmd?

iTerm ssh 自动登录

使用 ssh 远程登录时:

  1. 输入 ssh root@host-ip
  2. 输入密码

每次都重复这样的操作,不仅麻烦,还要记忆好多东西,为了解决这个问题,借助 iTerm2 Profile 可以实现 ssh 自动登录:

  1. 编写 expect 脚本
  2. 使用此脚本创建 Profile
  3. 使用此 Profile 打开新标签页

MySQL 导入导出 SQL 文件

创建数据库

1
CREATE DATABASE IF NOT EXISTS databaseName DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

导入 SQL 文件

MySQL 可以使用 GUI 客户端导入 SQL 文件,此外在命令行下有常用下面 2 种方式导入 SQL 文件(先要创建好数据库)

  • 使用 mysql 导入
    • 命令中不带密码
      1. ./mysql -uroot -p 数据库名 < 导入的文件名.sql
      2. 输入密码
    • 命令中带密码: ./mysql -uroot -p$password 数据库名 < 导入的文件名.sql
  • 使用 source 导入
    1. ./mysql -uroot -p
    2. 输入密码
    3. use databaseName
    4. source 导入的文件名.sql

导出 SQL 文件

导出有 2 种: 导出数据库(包含建表语句和表中的数据),导出表结构(只有建表语句)

  • 导出数据库: mysqldump -uusername -p 数据库名 > 导出的文件名.sql
  • 导出表结构: mysqldump -uusername -p -d 数据库名 > 导出的文件名.sql

自定义 Widget 使用 QSS

相信很多同学继承如 QWidget,QPushButton 等实现自定义的控件后,发现在此控件上 QSS 不生效了,这不行啊,设置背景、边框、字体等如果没有 QSS 那就太麻烦了。其实在自定义控件上启用 QSS 非常简单,只要调用一下 setAttribute(Qt::WA_StyledBackground) 即可,就像下面这样

1
2
3
4
Widget::Widget(QWidget *parent) : QWidget(parent) {
this->setAttribute(Qt::WA_StyledBackground); // 启用 QSS
this->setStyleSheet("border: 2px solid red; background: pink; border-radius: 10px;"); // 设置 QSS
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <QApplication>
#include "Widget.h"

int main(int argc, char *argv[]) {
QApplication app(argc, argv);

QWidget window;

Widget customWidget(&window);
customWidget.setGeometry(20, 20, 100, 100);

window.resize(300, 300);
window.show();

return app.exec();
}

如上在 main() 函数中使用自定义控件 Widget,QSS 生效了,去掉 this->setAttribute(Qt::WA_StyledBackground) 后 QSS 就没效果了:

按下鼠标拖动窗口

QWidget 已经实现了在标题栏按下鼠标移动窗口的功能,但是当实现无边框窗口时,因为没有了标题栏,移动窗口的功能就需要我们自己实现了,不过也不复杂,主要是处理鼠标的按下、移动、松开三个事件:

  • 按下鼠标:记录此时鼠标的全局坐标和窗口左上角的坐标,并且设置鼠标为按下状态
  • 移动鼠标:鼠标按下时移动鼠标,计算此时鼠标和鼠标按下时的位移差,加上按下鼠标时窗口左上角的坐标得到窗口新的坐标,移动窗口到此坐标
  • 松开鼠标:设置鼠标为未按下状态

拖拽鼠标画矩形

经常看到有同学问:如何实现用鼠标拖拽出一个矩形区域的效果,类似 QQ 截图的那个矩形区域?

很简单的一个问题,主要是处理鼠标的按下、移动、松开三个事件:

  • 按下鼠标:用一个变量标记要开始拖拽出矩形了,并记录按下的位置作为矩形的左上角顶点
  • 移动鼠标:按下时移动鼠标,鼠标的当前位置作为矩形新的右下角的顶点,每次移动事件发生时都要重新画一次矩形,因为矩形变了
  • 松开鼠标:清除拖拽矩形的标志,松开鼠标后,移动鼠标时就不要再改变矩形了

Qt Creator 简介

工欲善其事,必先利其器,顺手的开发工具,能够让我们事半功倍,Qt 开发,推荐使用 Qt Creator,因为在 Qt Creator 中集成了很多实用的功能,不需要切换到其他软件就能使用

  • 编写代码(废话)
  • 使用 UI Designer 进行可视化的布局界面
  • 搜索帮助文档
  • 学习自带的例子
  • Ctrl + K 快速搜索、定位

接下来就简单的介绍下我个人觉得 Qt Creator 使用中比较重要的地方。

线程池 QThreadPool

创建线程需要向系统申请资源,线程切换时操作系统会切换线程上下文,可能会从用户态切换到内核态,当有很多线程时,频繁地切换线程会导致消耗大量的 CPU 以及内核资源,真正用于计算的资源就减少了,反而会降低程序的效率。线程并不是越多越好,线程池的作用是管理、复用、回收一组线程,控制线程的数量,避免频繁的创建和销毁线程而浪费资源。

Qt 中的线程池类为 QThreadPool,每一个 Qt 程序都有一个全局的线程池,调用 QThreadPool::globalInstance() 得到,它默认最多创建 8 个线程,如果想改变最大线程数则调用 setMaxThreadCount() 进行修改,调用 activeThreadCount() 查看线程池中当前活跃的线程数。

使用线程池挺简单的,定一个任务类例如叫 Task,继承 QRunnable 并实现虚函数 run(),Task 的对象作为 QThreadPool::start() 的参数就可以了,线程池会自动的在线程中调用 Task 的 run() 函数,异步执行。线程池中的 QRunnable 对象太多时并不会为立即为每一个 QRunnable 对象创建一个线程,而是让它们排队执行,同时最多有 maxThreadCount() 个线程并行执行。

提交给线程池的 QRunnable 对象在它的 run() 函数执行完后会被自动 delete 掉,如果不想线程池删除它,在调用线程池的 start() 前调用 setAutoDelete(false) 即可。