在阅读本篇文章之前,请先注意以下几点声明:
-
1. 原文:
- Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further. 译文:
- 注意。此规范不再处于主动维护中,Web应用程序工作组不打算进一步维护它。
-
2. 原文:
- This document was on the W3C Recommendation track but specification work has stopped. The specification reached an impasse: all interested implementors have used the same SQL backend (Sqlite), but we need multiple independent implementations to proceed along a standardisation path. 译文:
- 这个文档是W3C推荐的,但是规范工作已经停止了。规范陷入了僵局:所有感兴趣的实现者都使用相同的SQL后端(Sqlite),但是我们需要多个独立的实现来沿着标准化的道路前进。
-
3. 原文:
- Each origin has an associated set of databases. Each database has a name and a current version. There is no way to enumerate or delete the databases available for an origin from this API. 译文:
- 每个起源都有一组相关联的数据库。每个数据库都有一个名称和当前版本。无法从此API枚举或删除源可用的数据库。
文章目录
一、简介
1. HTML5 Web SQL 数据库是什么?
- Web SQL Database API 并不是 HTML5 规范的一部分,但它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs;
- Web SQL Database 使用 SQL 来操纵客户端数据库的 API,这些 API 是异步的,规范中使用的是 SQLlite(SQL后端);
- Web SQL Database 可以在最新版的 Safari、Chrome 和 Opera 浏览器中工作;
- Web SQL Database 目前还没有删除数据库的 API,不支持删库;
- 曾被 W3C 推荐标准,现已被废弃,应避免使用…
2. 对应浏览器版本兼容表
3. 所拥有的属性及方法(API)
PS:红色为核心方法,绿色的三个是通过原型对象找到的(关于用法,后面会讲)。
- openDatabase() - 打开或新建一个数据库;
- transaction() - 读写数据库事务并提交或者回滚执行(rollback 函数);
- executeSql() - 执行实际的 SQL 查询语句;
- version - 返回数据库版本号;
- changeVersion() - 更改数据库版本号;
- readTransaction() - 只读数据库事务(rollback 函数);
二、操作数据库
1. 如何检测浏览器是否支持?
- 通过访问对象属性返回的布尔值检测:
if (window.openDatabase) {
// 浏览器支持执行的代码
} else {
alert('您的浏览器不支持 Web SQL Database。');
}
- 使用
key in obj
语法检测:
if ('openDatabase' in window) {
// 浏览器支持执行的代码
} else {
alert('您的浏览器不支持 Web SQL Database。');
}
- 使用
typeof
运算符检测:(localStorage 与 sessionStorage 使用typeof(Storage) !== ‘undefined’
检测)
// 检测 window 对象中是否存在 openDatabase 属性/方法(勿加引号成字符串)
if (typeof(openDatabase) !== 'undefined') {
// 浏览器支持执行的代码
} else {
alert('您的浏览器不支持 Web SQL Database。');
}
- 使用
try…catch(err)…
语句(最简洁方便):
try {
// 浏览器支持执行的代码
} catch (err) {
// 浏览器不支持或其它报错内容
alert(err);
}
2. 如何创建或打开数据库?
通过 openDatabase()
方法来创建或打开数据库(存在则打开,不存在则新建);
// 新建/打开数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
console.log(db); // Database 对象
对应的参数:
- “userdata” - 参数1,需要创建或打开的数据库;
- “1.0” - 参数2,数据库版本号,可修改,可为空,可为非数字,建议浮点数;
- “user-data” - 参数3,数据库描述,可为空;
- “2 * 1024 * 1024” - 参数4,数据库大小,此处为 2M(兆)【最大限制根据电脑硬盘情况而定】;
- 我用 Edge 显示的可用大小为 50G 左右,其中还含有其它页、其它浏览器、等等之类的缓存功能共用大小…
- 打开另一个页面,各类缓存同样使用该内存空间:
- 我用 Edge 显示的可用大小为 50G 左右,其中还含有其它页、其它浏览器、等等之类的缓存功能共用大小…
- 参数5 - 创建回滚(在创建数据库后被调用);
使用调试 console.log(db)
获取 Database 对象:(这些便是所拥有的 API)
3. 如何获取与修改版本号?
通过 version
属性来获取版本号;
通过 changeVersion()
方法来修改版本号(无法删除,除非使用空值替换);
// 修改版本号
db.changeVersion('1.0', '新版本号');
console.log(db.version); // 获取版本号
对应的参数:
- “1.0” - 原有的,旧版本号;
- “新版本号” - 新的,想要设置的版本号,可设置为任意字符串,但建议浮点数;
修改后需要修改对应的版号本才能打开数据库:
使用 console.log(db.version)
来获取版本号:(需打开数据库)
通过报错来获取版本号:(无需打开数据库,版本号不对自然报错提醒)
4. 如何创建与删除数据表?
通过 executeSql()
方法来执行 SQL查询语句,创建与删除数据表等操作;
a. 【创建数据表】
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 创建数据表并设置唯一
tx.executeSql('create table if not exists login (id unique, username, userpassword)');
console.log(tx); // SQLTransaction 对象
});
对应的参数:
- “function() {}” - 数据库事务(transaction)的回滚(rollback)函数;
- “tx” - 回滚函数的形参,指向 SQL 事务(SQLTransaction)对象;
- sql 参数:
- “if not exists” - 如果该数据表不存在,则执行创建语句;
- “login” - 需创建的数据表名;
- “id unique” - 设置 “id” 字段,并设为唯一(类似主键用于约束);
- 也可使用 “主键” 约束 “id” 字段:“id primary key”
使用 console.log(tx)
来获取版本号:(可以从返回的 SQLTransaction 对象中找到 executeSql()
方法)
对比 PHP 链接 MySQL 的语法:
<?php
$dbhost = 'localhost'; // mysql服务器主机地址
$dbuser = 'admin1'; // mysql用户名
$dbpass = 'admin1'; // mysql用户名密码
$dbdata = 'admin1'; // mysql数据库库名
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $dbdata);
// 关闭自动提交
mysqli_autocommit($conn, false);
// 插入数据
$sql = 'insert into login'.
'(user,password)'.
'values'.
'("'.$name.'","'.md5($password).'")';
$retval = mysqli_query($conn, $sql);
mysqli_commit($conn); // 提交事务
mysqli_rollback($conn); // 回滚事务
mysqli_close($conn); // 关闭数据库
?>
executeSql()
相当于mysqli_query()
用于执行 sql 语句;transaction()
,相当于 PHP 中的mysqli_rollback()
用于回滚执行;
b. 【删除数据表】
db.transaction(function(tx) {
// 删除数据表
tx.executeSql('drop table login');
});
三、操作数据
1. 增
a. 【单条插入】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 静态插入
tx.executeSql('insert into login (id, username, userpassword) values (1, "demo", "demo")');
// 动态插入(参数式)【推荐】
tx.executeSql('insert into login (id, username, userpassword) values (?, ?, ?)', [2, 'admin', 'admin']);
// 动态插入(字符串 '+' 拼接)
var id_a = 3;
var uname_a = '"abcd"';
var upw_a = '"abcd"';
tx.executeSql('insert into login (id, username, userpassword) values (' + id_a + ', ' + uname_a + ', ' + upw_a + ')');
// 动态插入(JSON 字符串式)
var id_b = 4;
var uname_b = JSON.stringify('aaaaaa');
var upw_b = JSON.stringify('bbbbbb');
tx.executeSql('insert into login (id, username, userpassword) values (' + id_b + ', ' + uname_b + ', ' + upw_b + ')');
// 动态插入(字符串 concat() 方法拼接)
var id_c = 5;
var uname_c = '"test"';
var upw_c = '"abc123"';
var str = 'insert into login (id, username, userpassword) values';
var sql = str.concat('(', id_c, ',', uname_c, ',', upw_c, ')');
tx.executeSql(sql);
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
需要注意的地方:
- 1)关于 sql 语句:
sql = ‘insert into login (id, username, userpassword) values (1, “demo”, “demo”)’;
- “insert into login” - 表示 “在 login 数据表中插入数据”;
- 其中,橙色为字段名,绿色为对应字段插入的值,即 id = 1, username = demo, userpassword = demo;
- 在 sql 中,字符串必须加引号(注意,并不是在 js 中加了引号,去到 sql 语句就是字符串);
- 错误格式:
- 正确格式1:(再加双引号)
- 正确格式2:(JSON 字符串格式)
- 为何
executeSql(sql, [1, ‘demo’, ‘demo’])
没有问题,而上面的情况需要再次双引号?
(因为经过处理,你看不见而已…这只是个例子,并表示官方如此处理)
- 2)关于
executeSql(sql, arr, function(){})
参数- sql - 数据库查询语句,用于对数据库进行操作;
- arr - 数组参数,存储用于匹配的 字段值 集合(仅能输入字段值,无法设置为字段名或其它);
- 其中,arr 参数,当没有涉及到函数参数(即三个参数)时,可不写;当需要执行函数时,数组参数必须写,可以为
[]
空数组; - 即:
executeSql(sql)
; - 即:
executeSql(sql, [value1, value2, …], function(){})
- 即:
executeSql(sql, [], function(){})
; - 错误写法:executeSql(sql, function(){})
- Uncaught TypeError: Failed to execute ‘executeSql’ on ‘SQLTransaction’: The object must have a callable @@iterator property.
- 未捕获类型错误:未能在’SQLTransaction’上执行’executeSql’:该对象必须具有可调用的@@iterator属性。
- 其中,arr 参数,当没有涉及到函数参数(即三个参数)时,可不写;当需要执行函数时,数组参数必须写,可以为
- function(){} - 回滚(rollback)函数,用于 js 控制(读取、输出、等 js 操作);
- 其中,function(){} 有两个参数:
- tx - 上面说过了,指向 SQL 事务对象(SQLTransaction);
- retval - 为 SQL 的返回值(数据);
- 其中,function(){} 有两个参数:
tx.executeSql('(?, ?, ?)', [对应第一个?, 对应第二个?, 对应第三个?], function(tx, retval) {
console.log('SQL的返回值:' + retval)
});
b. 【通过遍历逐条插入】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 创建年月日时分秒实例,自动补 '0'
var g_year = (new Date()).getFullYear();
var g_month = ((new Date()).getMonth()+1).toString().padStart(2,'0');
var g_date = ((new Date()).getDate()).toString().padStart(2,'0');
var g_hours = ((new Date()).getHours()).toString().padStart(2,'0');;
var g_minutes = ((new Date()).getMinutes()).toString().padStart(2,'0');;
var g_seconds = ((new Date()).getSeconds()).toString().padStart(2,'0');;
var data = [
{
id : 1,
username : '张三',
userpassword : 'demo123',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 2,
username : '李四',
userpassword : 'hao666',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 3,
username : '王五',
userpassword : '123456',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 4,
username : '赵六',
userpassword : 'ssssfff',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 5,
username : '田七',
userpassword : 'admin223399',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
]
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 通过遍历数据长度,逐条插入
for (var i = 0; i < data.length; i++) {
// 参数式
tx.executeSql('insert into login (id, username, userpassword, gettime) values (?, ?, ?, ?)', [data[i].id, data[i].username, data[i].userpassword, data[i].gettime]);
}
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
c. 【插入多条数据】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 创建年月日时分秒实例,自动补 '0'
var g_year = (new Date()).getFullYear();
var g_month = ((new Date()).getMonth()+1).toString().padStart(2,'0');
var g_date = ((new Date()).getDate()).toString().padStart(2,'0');
var g_hours = ((new Date()).getHours()).toString().padStart(2,'0');;
var g_minutes = ((new Date()).getMinutes()).toString().padStart(2,'0');;
var g_seconds = ((new Date()).getSeconds()).toString().padStart(2,'0');;
var data = [
{
id : 1,
username : '张三',
userpassword : 'demo123',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 2,
username : '李四',
userpassword : 'hao666',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 3,
username : '王五',
userpassword : '123456',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 4,
username : '赵六',
userpassword : 'ssssfff',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
{
id : 5,
username : '田七',
userpassword : 'admin223399',
gettime : g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds
},
]
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 参数式
tx.executeSql('insert into login (id, username, userpassword, gettime) values' +
'(?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?)',
[
data[0].id, data[0].username, data[0].userpassword, data[0].gettime,
data[1].id, data[1].username, data[1].userpassword, data[1].gettime,
data[2].id, data[2].username, data[2].userpassword, data[2].gettime,
data[3].id, data[3].username, data[3].userpassword, data[3].gettime,
data[4].id, data[4].username, data[4].userpassword, data[4].gettime
]);
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
2. 查
a. 【静态查询所有列】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(只读)
db.readTransaction(function(tx) {
// 静态查询(所有列)
tx.executeSql('select * from login', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(查询所有列表数据)');
console.log('//列出所有数据')
console.table(retval.rows);
});
// 静态查询(所有列)
tx.executeSql('select * from login where id=1', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配单字段查询所有数据)');
console.log('//列出符合 id = 1 的所有数据');
console.table(retval.rows);
});
// 静态查询(所有列)
tx.executeSql('select * from login where id=2 and username="admin" and userpassword="admin"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配多字段查询所有数据)');
console.log('//列出符合 id = 2, username = admin 的所有数据');
console.table(retval.rows);
});
// 静态查询(所有列)
tx.executeSql('select * from login where username like "d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询所有数据)');
console.log('//列出符合 username 字段值开头包含 "d" 的所有数据');
console.table(retval.rows);
});
// 静态查询(所有列)
tx.executeSql('select * from login where username like "%d"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询所有数据)');
console.log('//列出符合 username 字段值尾部包含 "d" 的所有数据');
console.table(retval.rows);
});
// 静态查询(所有列)
tx.executeSql('select * from login where username like "%d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(全模糊匹配单字段查询所有数据)');
console.log('//列出符合 username 字段值包含 "d" 的所有数据');
console.table(retval.rows);
});
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
b. 【静态查询单列】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(只读)
db.readTransaction(function(tx) {
// 静态查询(单列)
tx.executeSql('select userpassword from login', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(查询单字段/单列数据)');
console.log('//列出 userpassword 字段的所有数据')
console.table(retval.rows);
});
// 静态查询(单列)
tx.executeSql('select userpassword from login where id=1', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配单字段查询单列数据)');
console.log('//列出符合 id = 1 的 userpassword 字段的所有数据');
console.table(retval.rows);
});
// 静态查询(单列)
tx.executeSql('select userpassword from login where id=2 and username="admin"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配多字段查询单列数据)');
console.log('//列出符合 id = 2, username = admin 的 userpassword 字段的所有数据');
console.table(retval.rows);
});
// 静态查询(单列)
tx.executeSql('select userpassword from login where userpassword like "d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询单列数据)');
console.log('//列出符合 userpassword 字段值开头包含 "d" 的 userpassword 字段的所有数据');
console.table(retval.rows);
});
// 静态查询(单列)
tx.executeSql('select userpassword from login where userpassword like "%d"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询单列数据)');
console.log('//列出符合 userpassword 字段值尾部包含 "d" 的 userpassword 字段的所有数据');
console.table(retval.rows);
});
// 静态查询(单列)
tx.executeSql('select userpassword from login where userpassword like "%d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(全模糊匹配单字段查询所有数据)');
console.log('//列出符合 userpassword 字段值包含 "d" 的 userpassword 字段的所有数据');
console.table(retval.rows);
});
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
c. 【静态查询双列】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(只读)
db.readTransaction(function(tx) {
// 静态查询(双列)
tx.executeSql('select username, userpassword from login', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(查询两列数据)');
console.log('//列出 username, userpassword 字段所有数据')
console.table(retval.rows);
});
// 静态查询(双列)
tx.executeSql('select username, userpassword from login where id=1', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配单字段查询两列数据)');
console.log('//列出符合 id = 1 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
// 静态查询(双列)
tx.executeSql('select username, userpassword from login where id=2 and username="admin" and userpassword="admin"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(匹配多字段查询两列数据)');
console.log('//列出符合 id = 2, username = admin 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
// 静态查询(双列)
tx.executeSql('select username, userpassword from login where username like "d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询两列数据)');
console.log('//列出符合 username 字段值开头包含 "d" 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
// 静态查询(双列)
tx.executeSql('select username, userpassword from login where username like "%d"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(半模糊匹配单字段查询两列数据)');
console.log('//列出符合 username 字段值尾部包含 "d" 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
// 静态查询(双列)
tx.executeSql('select username, userpassword from login where username like "%d%"', [], function(tx, retval) {
// 控制台 table 输出
console.warn('静态查询(全模糊匹配单字段查询两列数据)');
console.log('//列出符合 username 字段值包含 "d" 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
d. 【动态查询】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(只读)
db.readTransaction(function(tx) {
// 动态查询(双列)
tx.executeSql('select username, userpassword from login where id=?', [1], function(tx, retval) {
// 控制台 table 输出
console.warn('动态查询(匹配单字段查询两列数据)');
console.log('//列出符合 id = 1 的 username, userpassword 字段所有数据');
console.table(retval.rows);
});
// 动态查询(所有列)
tx.executeSql('select * from login where id=? and username=? and userpassword=?', [2, 'admin', 'admin'], function(tx, retval) {
// 控制台 table 输出
console.warn('动态查询(匹配多字段查询所有数据)');
console.log('//列出符合 id = 2, username = admin 的所有数据');
console.table(retval.rows);
});
// 动态查询(双列)
tx.executeSql('select id, userpassword from login where username like ?', ['d%'], function(tx, retval) {
// 控制台 table 输出
console.warn('动态查询(半模糊匹配单字段查询两列数据)');
console.log('//列出符合 username 字段值开头包含 "d" 的 id, userpassword 字段所有数据');
console.table(retval.rows);
});
// 动态查询(单列)
tx.executeSql('select id from login where username like ?', ['%d'], function(tx, retval) {
// 控制台 table 输出
console.warn('动态查询(半模糊匹配单字段查询单数据)');
console.log('//列出符合 username 字段值尾部包含 "d" 的 id 字段的数据');
console.table(retval.rows);
});
// 动态查询(所有列)
tx.executeSql('select * from login where username like ?', ['%d%'], function(tx, retval) {
// 控制台 table 输出
console.warn('动态查询(全模糊匹配单字段查询所有数据)');
console.log('//列出符合 username 字段值包含 "d" 的所有数据');
console.table(retval.rows);
});
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
e. 更多的 SQL 查询...
太多了,就不写了,无非就是使用 sql 语句查询,知道怎么用 js 传递改变参数就行了…
需要注意的地方:
- 在查询数据中,我使用了
readTransaction()
方法,此方法为 只读 的 SQL 事务,无法进行修改删除等操作;当然你也可以使用transaction()
(可读可写),这在对数据进行读取中,并不影响,但readTransaction()
无法用于其它数据操作中(由于回滚原因不会报错,但值会无反应); - 关于 sql 中的参数:
- 模糊查询:
- 模糊查询并不是使用 ‘=’ 来匹配,而是 ‘like’:
sql = ‘select * from login where username like “%d%”’;
- ‘d%’ - 开头匹配 d,并对右边进行模糊查询;
- ‘%d’ - 尾部匹配 d,并对左边进行模糊查询;
- ‘%d%’ - 左右模糊查询,需匹配至少一个 d;
- 模糊查询并不是使用 ‘=’ 来匹配,而是 ‘like’:
- “select” ~ “from” 之间的参数,表示需要查询的字段,即想要查询哪几列;
- “select * from” - 查询所有字段,所有列的数据;
- “select id from” - 仅查询 id 字段,这一列的数据;
- “select username, userpassword from” - 仅查询 username, userpassword 字段,这两列的数据(注意,是逗号,不是 and);
- 正确写法:
select username, userpassword from login;
- 错误写法:
select username and userpassword from login;
- 同样的,所有 SQL 查询语句中,多个字段名匹配用逗号连接,而字段值则采用 and 连接:
- 如修改数据亦如此(下面会说);
- 模糊查询:
3. 改
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 静态修改
tx.executeSql('update login set userpassword="change" where id=1');
// 动态修改(参数式)【推荐】
tx.executeSql('update login set username=? , userpassword=? where id=?', ['id2', 'change', 2]); // 改双值
// 动态修改(字符串 '+' 拼接)
var id_a = 3;
var uname_a = '"id3"'; // 需要修改的值
var upw_a = '"change"'; // 需要修改的值
tx.executeSql('update login set username=' + uname_a + ', userpassword=' + upw_a + ' where id=' + id_a); // 改双值
// 动态修改(JSON 字符串式)
var uname_b = JSON.stringify('aaaaaa');
var upw_b = JSON.stringify('change'); // 需要修改的值
tx.executeSql('update login set userpassword=' + upw_b + ' where username=' + uname_b);
// 动态修改(字符串 concat() 方法拼接)
var id_c = 5;
var uname_c = '"test"';
var upw_c = '"change"';
var str1 = 'update login set userpassword=';
var str2 = ' where username=';
var str3 = ' and id='
var sql = str1.concat(upw_c, str2, uname_c, str3, id_c);
tx.executeSql(sql);
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
需要注意的地方:
- 在查询数据中写需注意的地方也有提到,所有 SQL 查询语句中,多个字段名匹配用逗号连接,而字段值则采用 and 连接:
4. 删
a. 【单条删除】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 静态删除
tx.executeSql('delete from login where id=1');
// 动态删除(参数式)【推荐】
// tx.executeSql('delete from login where id=?', [2]); // 单字段匹配
tx.executeSql('delete from login where id=? and userpassword=?', [2, 'change']); // 多字段匹配
// 动态删除(字符串 '+' 拼接)
var uname_a = '"id3"';
var upw_a = '"change"';
// tx.executeSql('delete from login where username=' + uname_a); // 不推荐单查询非唯一字段
tx.executeSql('delete from login where username=' + uname_a + ' and userpassword=' + upw_a); // 多字段匹配
// 动态删除(JSON 字符串式)
var uname_b = JSON.stringify('aaaaaa');
var upw_b = JSON.stringify('change');
tx.executeSql('delete from login where username=' + uname_b + ' and userpassword=' + upw_b); // 多字段匹配
// 动态删除(字符串 concat() 方法拼接)
var id_c = 5;
var uname_c = '"test"';
var upw_c = '"change"';
var str1 = 'delete from login where id=';
var str2 = ' and username=';
var str3 = ' and userpassword='
// var sql = str1.concat(id_c); // 单字段匹配
var sql = str1.concat(id_c, str2, uname_c, str3, upw_c); // 多字段匹配
tx.executeSql(sql);
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
b. 【通过遍历逐条删除】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 获取所有 id 值,再遍历,当然,也可以用 * 通配符,能获取到所有数据行数即可
tx.executeSql('select id from login', [], function(tx, retval) {
// 获取返回结果的行数
var len = retval.rows.length;
// 通过遍历,进行逐行 id 匹配删除数据
for (var i = 0; i < len; i++) {
var ids = retval.rows[i].id;
// 拼接式
// tx.executeSql('delete from login where id=' + ids);
// 参数式
tx.executeSql('delete from login where id=?', [ids]);
}
});
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
c. 【删除所有数据】
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="retval"></div>
<script type="text/javascript">
// 检测浏览器是否支持或报错
try {
// 创建/打开 userdata 数据库
var db = openDatabase('userdata', '1.0', 'users data', 2 * 1024 * 1024);
// 数据库事务操作(读写)
db.transaction(function(tx) {
// 清空数据表数据
tx.executeSql('delete from login');
});
} catch (err) {
alert(err);
}
</script>
</body>
</html>
需要注意的地方:
- 遍历删除数据,需要先获取得到数据,才能进行匹配删除,而只有
select 字段名 from 表名
语句才会返回 sql 的值。 sql = ‘delete from login’
清空数据表,保留表;sql = ‘drop table login’
则删除表;
四、一些适用于 Web SQL 的 SQL 查询语句
SQL 运算符、操作符、通配符速查表
运算符 | 描述 |
---|---|
AND(并且) | 如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。 |
OR(或者) | 如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。 |
NOT(非) | 用于否定条件,取反。 |
, (逗号) | 用于 "UPDATE、SELECT" 主句,"ORDER BY" 子句,用于拼接多项列。 |
操作符 | 描述 |
---|---|
= | 等于 |
<> 或 != | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
BETWEEN | 在某个范围内 |
IN | 在规定单或多个值内 |
LIKE | 搜索某种模式(大小写不敏感) |
GLOB | 搜索某种模式(大小写敏感) |
通配符 | 描述 |
---|---|
% | (LINK 使用)替代零个、一个或多个字符或数字 |
_ | (LINK 使用)仅替代一个字符或数字 |
[charlist] | (LINK 使用)字符列中的任何单一字符或数字 |
[^charlist] 或 [!charlist] | (LINK 使用)不在字符列中的任何单一字符或数字 |
* | (GLOB 使用)替代零个、一个或多个字符或数字 |
? | (GLOB 使用)仅替代一个字符或数字 |
前提:如何使用浏览器输入 SQL 语句操作 Web SQL Database?
- 首先,你必须得用 js 脚本为当前网站创建或打开一个 Web SQL 数据库(最好使用 html 文件的 js 脚本打开,因为这个库,一刷新页面又没了,需要一个"索引"来连接它,别以为它没了就会销毁,它只是消失了,但数据还会保留的):
- 使用 html 文件 js 脚本连接数据库,并打开页面:
- 打开数据库,在库的那项中,就能输入 SQL 语句了:
- 输入关键字时,会有提示,按 “→” 自动填充,前往别按 “Enter” (回车键),它会之间中断输入执行语句:
- 通过输入 SQL 语句对数据进行操作,插入、修改、删除、查询:
- 错误语句报错:
- 一个数据库可创建多个数据表:
1. 创建数据表并设置字段:
关键字
a. 【"IF NOT EXISTS"】
“如果不存在(就执行)”:设置此关键词后,即使创建同名表不成功也不会报错(报错会中断后继执行,特别在用 JS 控制的时候)。
CREATE TABLE IF NOT EXISTS 表名(字段1, 字段2, 字段3, ...);
约束
b. 【NOT NULL】
“非空”:指示某列不能存储 NULL 值。
CREATE TABLE 表名 (字段1 NOT NULL, 字段2, 字段3, ...);
c. 【UNIQUE】
“唯一”:保证某列的每行必须有唯一的值。
CREATE TABLE 表名 (字段1 UNIQUE, 字段2, 字段3, ...);
d. 【CHECK】
“核查”:保证列中的值符合指定的条件。如:check(a>10),表示 a 字段的值只能大于 10,否则报错。
CREATE TABLE 表名 (字段1 CHECK(限制条件), 字段2, 字段3, ...);
注意,当值为非数字时,不会报错,这个是 Web SQL 的问题,本来需要设置 int 类型的,这里设置了无效。
e. 【DEFAULT】
“默认”:规定没有给列赋值时的默认值。如:default ‘0’,当该字段不插入值时,自动插入 “0” 值。
CREATE TABLE 表名 (字段1 DEFAULT '默认值', 字段2, 字段3, ...);
f. 【PRIMARY KEY】
“主键”:NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
CREATE TABLE 表名 (字段1 PRIMARY KEY, 字段2, 字段3, ...);
可得出:在这里,主键已经废了,仅仅只有 “唯一” 特性的主键,那干嘛不用 “唯一” 约束?
g. 【PRIMARY KEY()】
“复合主键”:在同一个表内设置多个"主键"。
CREATE TABLE 表名 (字段1, 字段2, 字段3, ..., PRIMARY KEY(字段1, 字段2, 字段3, ...));
复合主键也已经废了,仅仅只有 “唯一” 特性…
数据类型
Web SQL 问题真多,int、varchar等数据类型虽然能设置,但是没有限制值的输入,比如,虽然设置了 int 整数型,但你插入字符串也可以…
所以,这些数据类型在这里是废了,可以舍弃不用了,还有什么自增属性等也失效了…
h. 【TIMESTAMP】
“时间戳”:以 “年-月-日 时-分-秒” 的格式插入值。
CREATE TABLE 表名 (字段1 TIMESTAMP, 字段2, 字段3, ...);
- 时间类有四种:DATE(日期)、TIME(时间)、DATETIME(日期时间)、TIMESTAMP(时间戳),但在 Web SQL 中,四种时间插入的值都是相同的,所以选一个即可,推荐 “TIMESTAMP”(时间戳)
【Web SQL 的问题,虽然很多正确的 SQL 语句没报错,但却没有得到理想的结果】
其他属性
i. 【CURRENT_TIMESTAMP】
“当前时间戳”:跟随其它字段值的插入而自动添加时间戳。
// 时间戳
CREATE TABLE 表名 (字段1 TIMESTAMP CURRENT_TIMESTAMP, 字段2, 字段3, ...);
- 综上,有很多 SQL 语句在 Web SQL 中都失效了,现在又没有人去维护它,可以说 Web SQL 已经是个残缺品了,怪不得被废弃…
- SQL语句并不区分大小写,但字段值区分大小写,比如:username=“demo”。
- 可识别:
sql = ‘select username from login where USERname=“demo”’;
- 不可识别:
sql = ‘select username from login where username=“DEMO”’;
- 可识别:
2. 删除数据表
区分:DELETE FROM 表名,这个是清空表,保留字段,保留表,但 DROP TABLE 表名 是删除、摧毁表,不保留字段;
DROP TABLE 已存在表名;
3. 插入数据
插入值
a. 【对应字段名插入值】(插入单条)
INSERT INTO 表名 VALUES (值1, 值2, 值3, ...);
- 此举需对应字段名位置插入值:
- 插入值少一个不行,多一个也不行:
b. 【指定字段名插入值】(插入单条)
INSERT INTO 表名 (字段1, 字段2) VALUES (值1, 值2);
- 对指定字段进行插入值:
- 也要对应所指定的字段名插入值,同样多一个值不行,少一个值不行:
c. 【对应字段名插入值】(插入多条)
INSERT INTO 表名 VALUES (值1, 值2, 值3, ...), (值x, 值y, 值z, ...), ...;
- 一个括号代表一行值,括号内的值对应字段位置插入多行值:
- (括号内)也是多一个值不行,少一个值不行:
d. 【指定字段名插入值】(插入多条)
INSERT INTO 表名 (字段1, 字段2) VALUES (值1, 值2), (值x, 值y), ...;
- 按指定字段,插入多行值:
- 同样的,(括号内)多一个值不行,少一个值不行:
新增列
e. 【尾部插入字段名】(新增单列)
只有尾部插入列是可用的,其它什么开头插入列、修改字段数据类型、删除列均失效或报错…
ALTER TABLE 表名 ADD 字段名 数据类型;
// 或者
ALTER TABLE 表名 ADD COLUMN 字段名 数据类型;
- 不需要设置数据类型,因为数据类型在 Web SQL 中失效了…
4. 修改数据
逐个修改 单/多 项
a. 【匹配单字段值修改单项值】(修改单项)
UPDATE 表名 SET 字段 = 想改的值 WHERE 字段 = 值;
b. 【匹配多字段值修改单项值】(修改单项)
UPDATE 表名 SET 字段 = 想改的值 WHERE 字段1 = 值1 AND 字段2 = 值2 AND ...;
c. 【匹配单字段值修改多项值】(修改多项)
UPDATE 表名 SET 字段x = 想改的值, 字段y = 想改的值, ... WHERE 字段1 = 值1;
d. 【匹配多字段值修改多项值】(修改多项)
UPDATE 表名 SET 字段x = 想改的值, 字段y = 想改的值, ... WHERE 字段1 = 值1 AND 字段2 = 值2 AND ...;
批量修改 单/多 列
e. 【修改单列同值】(修改单列)
UPDATE 表名 SET 字段 = 想改的值;
f. 【修改多列同值】(修改多列)
UPDATE 表名 SET 字段1 = 想改的值1, 字段2 = 想改的值2, ...;
5. 查询数据(N种查询…)
“SELECT” 主句
a. 【选取所有列】
SELECT * FROM 表名;
b. 【选取单列】
SELECT 字段 FROM 表名;
c. 【选取多列】
SELECT 字段1, 字段2, ... FROM 表名;
“WHERE” 子句
d. 【"=" 等于】
注意:如果希望精确到一行,可选择唯一字段,来精确匹配。
SELECT * FROM 表名 WHERE 字段 = 值;
e. 【"<> 或 !=" 不等于】
SELECT * FROM 表名 WHERE 字段 <> 值;
// 或者
SELECT * FROM 表名 WHERE 字段 != 值;
f. 【">" 大于】
“>=” 大于等于同理
注意:一般用于筛选数值(不带引号),而不是字符串;非数值项被保留…
SELECT * FROM 表名 WHERE 字段 > 值;
g. 【"<" 小于】
“<=” 小于等于同理
注意:一般用于筛选数值(不带引号),而不是字符串;在这里居然筛掉了非数值项。
SELECT * FROM 表名 WHERE 字段 < 值;
“NOT、AND、OR、逗号” 运算符
h. 【"NOT" 否定】(子句)
SELECT * FROM 表名 WHERE NOT 条件;
i. 【"AND" 和/并且】(子句)
SELECT * FROM 表名 WHERE 条件1 AND 条件2;
j. 【"OR" 或者】(子句)
SELECT * FROM 表名 WHERE 条件1 OR 条件2;
k. 【"," 逗号】(主句)
SELECT 列1, 列2 FROM 表名;
“BETWEEN” 操作符,区间查询
l. 【区间值为数值时】
SELECT * FROM 表名 WHERE 字段 BETWEEN 数值1 AND 数值2;
m. 【区间值为字符串时】
SELECT * FROM 表名 WHERE 字段 BETWEEN 字符串1 AND 字符串2;
“IN” 操作符,范围查询
n. 【"IN" 在之内】
SELECT * FROM 表名 WHERE 字段 IN (值1, 值2, 值3, ...);
“ORDER BY” 子句,排序查询
o. 【"ASC" 升序/顺序】
SELECT * FROM 表名 ORDER BY 列 ASC;
p. 【"DESC" 降序/倒序】
SELECT * FROM 表名 ORDER BY 列 DESC;
q. 【升序、降序搭配】
注意:第一个排序条件优先级最大,第二个紧跟其后…
SELECT * FROM 表名 ORDER BY 列1 ASC, 列2 DESC, 列3 ...;
// 或者
SELECT * FROM 表名 ORDER BY 列1 DESC, 列2 ASC, 列3 ...;
“LIKE” 操作符,模糊查询(不区分大小写)
r. 【"%" 替代任意数量字符或数字】
// 值中,有"字符串"
SELECT * FROM 表名 WHERE 列 LIKE '%字符%';
// 值中,"字符串"开头
SELECT * FROM 表名 WHERE 列 LIKE '字符%';
// 值中,"字符串"结尾
SELECT * FROM 表名 WHERE 列 LIKE '%字符';
// 值中,开头结尾固定,中间模糊查询
SELECT * FROM 表名 WHERE 列 LIKE '字符%字符';
s. 【"_" 仅替代一个字符或数字】
// 开头结尾各替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '_字符串_';
// 开头结尾各替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '___字符串________';
// 开头替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '_字符串';
// 开头替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '______字符串';
// 结尾替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串_';
// 结尾替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串_______';
// 中间替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串_字符串';
// 中间替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串______字符串';
"[charlist]、[^charlist]、[!charlist]" 失效
“GLOB” 操作符,模糊查询(区分大小写)
t. 【"*" 替代任意数量字符或数字】
// 值中,有"字符串"
SELECT * FROM 表名 WHERE 列 GLOB '*字符*';
// 值中,"字符串"开头
SELECT * FROM 表名 WHERE 列 GLOB '字符*';
// 值中,"字符串"结尾
SELECT * FROM 表名 WHERE 列 GLOB '*字符';
// 值中,开头结尾固定,中间模糊查询
SELECT * FROM 表名 WHERE 列 GLOB '字符*字符';
u. 【"?" 仅替代一个字符或数字】
// 开头结尾各替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '?字符串?';
// 开头结尾各替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '???字符串????';
// 开头替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '?字符串';
// 开头替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '?????字符串';
// 结尾替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串?';
// 结尾替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串?????';
// 中间替换一个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串?字符串';
// 中间替换多个字符
SELECT * FROM 表名 WHERE 列 LIKE '字符串????字符串';
“GROUP BY” 子句,分组查询
v. 【对某列进行分组】
分组后,保留最先插入的数据。
SELECT * FROM 表名 GROUP BY 列;
w. 【"SUM()" 列求和】
注意:SUM() 函数,只保留数字,对非数字的字符自动转换成 “0”,比如 “aa445aa”,转换成 “445”;“aa”,转换成 “0”。
SUM() 将列的数据进行求和,与 GROUP BY 配合,对合并的数据进行求和统计。
SELECT 列1, SUM(列2), SUM(列3), ... FROM 表名 GROUP BY 需操作的列;
“HAVING” 子句,过滤分组查询
x. 【过滤出现次数】
SELECT * FROM 表名 GROUP BY 列 HAVING COUNT(列) 操作符 次数;
“DISTINCT” 关键字,去重查询
y. 【单列去重】
SELECT DISTINCT 列 FROM 表名;
z. 【多列去重】
SELECT DISTINCT 列1, 列2, 列3, ... FROM 表名;
“OFFSET、LIMIT” 子句,限制查询
aa. 【"LIMIT" 查询多少行】
SELECT * FROM 表名 LIMIT 查询行数;
【"OFFSET" 从第几行开始】不支持
6. 删除数据
a. 【单行删除】
DELETE FROM 表名 WHERE 字段 = 值;
a. 【清空数据表】
区分:DELETE FROM 表名,是清空表,保留字段,保留表,但 DROP TABLE 表名 是删除、摧毁表,不保留字段;
DELETE FROM 表名;
五、Web SQL Database实例
代码虽然粗制滥造,但能实现功能就懒得改了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
body {min-width: 625px;}
.signup, .update {float: left;padding: 20px;border: 1px solid #c3c3c3;}
.signup {margin-right: 10px;}
.wrap {text-align: center;}
input[type="button"] {margin: 0 10px;padding: 5px 20px;}
#mask {display: none;}
</style>
<script type="text/javascript">
window.onload = function() {
// 表单
var uname = document.getElementById('uname');
var upw = document.getElementById('upw');
var get_uname = document.getElementById('get_uname');
var show_data = document.getElementById('show_data');
var newpw = document.getElementById('newpw');
var msg = document.getElementById('msg');
msg.innerHTML = '';
// 按钮
var sub_btn = document.getElementById('sub_btn');
var rst_btn = document.getElementById('rst_btn');
var chg_btn = document.getElementById('chg_btn');
var del_btn = document.getElementById('del_btn');
var confirm = document.getElementById('confirm');
var show_btn = document.getElementById('show_btn');
var clr_btn = document.getElementById('clr_btn');
// 隐藏、显示
var mask = document.getElementById('mask');
// 数据库信息
var db_data = {
dbName : 'userdata',
dbVersion : '1.0',
dbtag : 'users data',
dbRAM : 2 * 1024 * 1024
}
// 创建年月日时分秒实例,自动补 '0'
var g_year = (new Date()).getFullYear();
var g_month = ((new Date()).getMonth()+1).toString().padStart(2,'0');
var g_date = ((new Date()).getDate()).toString().padStart(2,'0');
var g_hours = ((new Date()).getHours()).toString().padStart(2,'0');;
var g_minutes = ((new Date()).getMinutes()).toString().padStart(2,'0');;
var g_seconds = ((new Date()).getSeconds()).toString().padStart(2,'0');;
var gettime = g_year+'-'+g_month+'-'+g_date+' '+g_hours+':'+g_minutes+':'+g_seconds;
try {
var db = openDatabase(db_data.dbName, db_data.dbVersion, db_data.dbtag, db_data.dbRAM);
// 自动创建数据表(若不存在)
db.transaction(function(tx) {
tx.executeSql('create table if not exists login (id unique, username, userpassword, gettime)');
});
// 注册账号
sub_btn.onclick = function() {
db.transaction(function(tx) {
// 查询账号是否存在
tx.executeSql('select * from login where username=?', [uname.value], function(tx, retval) {
if (retval.rows.length > 0) {
msg.innerHTML = '错误提示:账号已存在,请重新输入!';
} else {
// 查询所有账号
tx.executeSql('select * from login', [], function(tx, retval) {
// 获取最后一项 id,并自增
var uid;
var len = retval.rows.length;
if (len > 0) {
uid = retval.rows[len-1].id + 1;
} else {
uid = 1;
}
if (uname.value !== '' && upw.value !== '') {
// 插入数据
tx.executeSql('insert into login (id, username, userpassword, gettime) values (?, ?, ?, ?)',
[uid, uname.value, upw.value, gettime], function() {
alert('注册成功!');
uname.value = '';
upw.value = '';
msg.innerHTML = '';
});
} else {
msg.innerHTML = '错误提示:请勿提交空值!';
}
});
}
});
});
};
// 修改查询
chg_btn.onclick = function() {
db.transaction(function(tx) {
if (get_uname.value !== '') {
// 判断是否存在账号
tx.executeSql('select * from login where username=?', [get_uname.value], function(tx, retval) {
if (retval.rows.length > 0) {
if (mask.getAttribute('data-disable') === null) {
// 初始计数
var i = 0;
// 计时器淡入
setInterval(function() {
if (i < 10) {
i++;
mask.style.display = 'block';
mask.style.opacity = i/10;
}
}, 100);
// 控制开关,防止反复点击
mask.setAttribute('data-disable', 'on');
}
} else {
msg.innerHTML = '错误提示:账号不存在,请重新输入!';
}
});
} else {
msg.innerHTML = '错误提示:请勿提交空值!';
}
});
msg.innerHTML = '';
}
// 修改密码
confirm.onclick = function() {
db.transaction(function(tx) {
if (newpw.value !== '') {
// 检测账号是否存在
tx.executeSql('select * from login where username=?', [get_uname.value], function(tx, retval) {
// 判断密码是否存在
if (newpw.value !== retval.rows[0].userpassword) {
// 修改密码
tx.executeSql('update login set userpassword=? where username=?', [newpw.value, get_uname.value], function() {
get_uname.value = '';
newpw.value = '';
alert('新密码修改成功!');
});
} else {
msg.innerHTML = '错误提示:请勿与原密码相同!';
}
});
} else {
msg.innerHTML = '错误提示:请勿提交空值!';
}
});
}
// 删除账号
del_btn.onclick = function() {
db.transaction(function(tx) {
if (get_uname.value !== '') {
// 判断是否存在账号
tx.executeSql('select * from login where username=?', [get_uname.value], function(tx, retval) {
if (retval.rows.length > 0) {
tx.executeSql('delete from login where username=?', [get_uname.value]);
alert('账号删除成功!');
get_uname.value = '';
} else {
msg.innerHTML = '错误提示:账号不存在,请重新输入!';
}
});
} else {
msg.innerHTML = '错误提示:请勿提交空值!';
}
});
};
// 查询所有账号(只读)
show_btn.onclick = function() {
db.readTransaction(function(tx) {
// 查询所有数据
tx.executeSql('select * from login', [], function(tx, retval) {
var dt_rows = retval.rows;
var html = '<table border="1"><tr><th>id</th><th>账号</th><th>密码</th><th>注册时间</th></tr>';
// 遍历输出
for (var i = 0; i < dt_rows.length; i++) {
html += '<tr><td>' + dt_rows[i].id +
'</td><td>' + dt_rows[i].username +
'</td><td>' + dt_rows[i].userpassword +
'</td><td>' + dt_rows[i].gettime +
'</td></tr>';
}
html += '</table>';
show_data.innerHTML = html;
msg.innerHTML = '';
});
});
}
// 清空所有账号
clr_btn.onclick = function() {
db.transaction(function(tx) {
tx.executeSql('delete from login');
show_data.innerHTML = '';
});
}
// 重置表单
rst_btn.onclick = function() {
uname.value = '';
upw.value = '';
msg.innerHTML = '';
}
} catch (err) {
msg.innerHTML = '错误提示:' + err;
}
}
</script>
</head>
<body>
<div class="signup">
<h3>账号注册</h3>
<p>账  号:<input type="text" id="uname"></p>
<p>密  码:<input type="password" id="upw"></p>
<p class="wrap">
<input type="button" id="sub_btn" value="提交" />
<input type="button" id="rst_btn" value="重置" />
</p>
</div>
<div class="update">
<h3>账号操作</h3>
<p>查询账号:<input type="text" id="get_uname"></p>
<p class="wrap">
<input type="button" id="chg_btn" value="修改密码" />
<input type="button" id="del_btn" value="删除账号" />
</p>
<div id="mask">
<h3>修改密码</h3>
<p>新的密码:<input type="password" id="newpw" /></p>
<p><input type="button" id="confirm" value="确定修改" /></p>
</div>
</div>
<div style="clear: both;">
<p>
<h3>数据操作</h3>
<input type="button" id="show_btn" value="显示所有账号" />
<input type="button" id="clr_btn" value="清空所有账号" />
</p>
<div id="show_data"></div>
</div>
<div id="msg" style="color: red;"></div>
</body>
</html>