超过电子表格

rDBMS 提供了多种将数据存储到其存储系统中的方式:从 CSV 文件、Excel 文件、特定产品的二进制文件,通过多个 API 或专用网关连接到其他数据库或数据库系统,以及其他一些技术。因此,存在广泛的——非标准化的——将数据引入我们系统的可能性。由于我们讨论的是 SQL,我们使用标准化的 INSERT 命令来完成这项工作。它在所有系统上都是可用的。

我们仅使用少量数据,因为我们希望保持简单。有时需要大量行来进行性能测试。为此,我们在本页末尾展示了一个特殊的 INSERT 命令,它可以指数级地膨胀您的表格。

person


-- 在进行大量测试后,我们可能希望将数据重置为原始版本。
-- 为此,使用 DELETE 命令。但请注意外键:您可能被迫最后删除
-- person 表中的记录 —— 使用 DELETE 时,删除表的顺序与 INSERT 时相反。
-- 请小心,不要将 DELETE 与 DROP 混淆 !!
--
-- DELETE FROM person_hobby;
-- DELETE FROM hobby;
-- DELETE FROM contact;
-- DELETE FROM person;
-- COMMIT;

INSERT INTO person VALUES (1,  'Larry',  'Goldstein', DATE'1970-11-20', 'Dallas',        '078-05-1120', 95);
INSERT INTO person VALUES (2,  'Tom',    'Burton',    DATE'1977-01-22', 'Birmingham',    '078-05-1121', 75);
INSERT INTO person VALUES (3,  'Lisa',   'Hamilton',  DATE'1975-12-23', 'Richland',      '078-05-1122', 56);
INSERT INTO person VALUES (4,  'Kim',    'Goldstein', DATE'2011-06-01', 'Shanghai',      '078-05-1123', 11);
INSERT INTO person VALUES (5,  'James',  'de Winter', DATE'1975-12-23', 'San Francisco', '078-05-1124', 75);
INSERT INTO person VALUES (6,  'Elias',  'Baker',     DATE'1939-10-03', 'San Francisco', '078-05-1125', 55);
INSERT INTO person VALUES (7,  'Yorgos', 'Stefanos',  DATE'1975-12-23', 'Athens',        '078-05-1126', 64);
INSERT INTO person VALUES (8,  'John',   'de Winter', DATE'1977-01-22', 'San Francisco', '078-05-1127', 77);
INSERT INTO person VALUES (9,  'Richie', 'Rich',      DATE'1975-12-23', 'Richland',      '078-05-1128', 90);
INSERT INTO person VALUES (10, 'Victor', 'de Winter', DATE'1979-02-28', 'San Francisco', '078-05-1129', 78);
COMMIT;

请注意,DATE 的格式可能取决于您的本地环境。此外,SQLite 使用不同的语法将字符串隐式转换为 DATE

-- SQLite 语法
INSERT INTO person VALUES (1,  'Larry',  'Goldstein', DATE('1970-11-20'), 'Dallas',      '078-05-1120', 95);
...

contact


-- DELETE FROM contact;
-- COMMIT;

INSERT INTO contact VALUES (1,  1,  'fixed line', '555-0100');
INSERT INTO contact VALUES (2,  1,  'email',      'larry.goldstein@acme.xx');
INSERT INTO contact VALUES (3,  1,  'email',      'lg@my_company.xx');
INSERT INTO contact VALUES (4,  1,  'icq',        '12111');
INSERT INTO contact VALUES (5,  4,  'fixed line', '5550101');
INSERT INTO contact VALUES (6,  4,  'mobile',     '10123444444');
INSERT INTO contact VALUES (7,  5,  'email',      'james.dewinter@acme.xx');
INSERT INTO contact VALUES (8,  7,  'fixed line', '+30000000000000');
INSERT INTO contact VALUES (9,  7,  'mobile',     '+30695100000000');
COMMIT;

hobby


-- DELETE FROM hobby;
-- COMMIT;

INSERT INTO hobby VALUES (1,  'Painting',
                                  'Applying paint, pigment, color or other medium to a surface.');
INSERT INTO hobby VALUES (2,  'Fishing',
                                  'Catching fishes.');
INSERT INTO hobby VALUES (3,  'Underwater Diving',
                                  'Going underwater with or without breathing apparatus (scuba diving / breath-holding).');
INSERT INTO hobby VALUES (4,  'Chess',
                                  'Two players have 16 figures each. They move them on an eight-by-eight grid according to special rules.');
INSERT INTO hobby VALUES (5,  'Literature', 'Reading books.');
INSERT INTO hobby VALUES (6,  'Yoga',
                                  'A physical, mental, and spiritual practices which originated in ancient India.');
INSERT INTO hobby VALUES (7,  'Stamp collecting',
                                  'Collecting of post stamps and related objects.');
INSERT INTO hobby VALUES (8,  'Astronomy',
                                  'Observing astronomical objects such as moons, planets, stars, nebulae, and galaxies.');
INSERT INTO hobby VALUES (9,  'Microscopy',
                                  'Observing very small objects using a microscope.');
COMMIT;

person_hobby


-- DELETE FROM person_hobby;
-- COMMIT;

INSERT INTO person_hobby VALUES (1, 1, 1);
INSERT INTO person_hobby VALUES (2, 1, 4);
INSERT INTO person_hobby VALUES (3, 1, 5);
INSERT INTO person_hobby VALUES (4, 5, 2);
INSERT INTO person_hobby VALUES (5, 5, 3);
INSERT INTO person_hobby VALUES (6, 7, 8);
INSERT INTO person_hobby VALUES (7, 4, 4);
INSERT INTO person_hobby VALUES (8, 9, 8);
INSERT INTO person_hobby VALUES (9, 9, 9);
COMMIT;

每一行 person_hobby 表包含一个来自 person 表的 id 和一个来自 hobby 表的 id。这是将人物和爱好信息关联起来的技术。

结构的可视化

执行上述命令后,您的数据库应包含四个表(没有任何数据)。这些表及其相互关系可以在所谓的实体关系图(Entity Relationship Diagram)中可视化。左侧是 personcontact 之间的 1:n 关系,右侧是 personhobby 之间的 n:m 关系,以及其中间的 person_hobby 表。


您可以根据需要复制/粘贴这些示例,以帮助您学习和实践SQL。

超大数据量

为了进行现实的性能测试,我们需要大量的数据。我们示例数据库中仅有的几行数据无法满足这一标准。我们如何生成测试数据并将其存储到表中?有多种可能性:在过程中的 FOR 循环,(伪)递归调用,以系统特定的方式导入外部数据,以及其他一些方法。

由于我们正在处理 SQL,我们介绍一个跨所有 rDBMS 可移植的 INSERT 命令。尽管它的语法简单,但功能非常强大。每次执行,它将使行数翻倍。假设表中有 1 行。第一次执行后,表中将有第二行。乍一看,这听起来很无聊。但经过 10 次执行后,行数超过一千,20 次执行后超过一百万,我们怀疑只有极少数安装能够执行超过 30 次。

INSERT INTO person (id,                                firstname, lastname, weight)
SELECT              id + (SELECT MAX(id) FROM person), firstname, lastname, weight
FROM        person;
COMMIT;

该命令是 INSERT 与(子)SELECT 的组合。SELECT 检索表中的所有行,因为没有 WHERE 子句。这就是行数翻倍的原因。强制性的列 firstnamelastname 保持不变。我们忽略了可选列。只有主键 id 被计算。新值是旧值加上执行命令时的最高可用 id

其他备注:

  1. MAX(id) 仅在每次执行时确定一次! 这说明了 rDBMS 的一个基本方面:在概念层面上,数据库在执行命令前具有特定的状态,在执行命令后具有新的状态。命令是将数据库从一个状态移动到另一个状态的原子操作——它们要么完全执行,要么完全不执行!SELECT 和内部 SELECT(使用 MAX(id))都在初始状态上操作。它们永远不会看到 INSERT 的结果或中间结果。否则,INSERT 将永远不会结束。

  2. 如果我们希望观察增长过程,可以向表中添加一列,以在每次迭代时存储 MAX(id)

  3. 如果 DBMS 支持自动递增列,可以省略新 id 的计算。

  4. 对于性能测试,可能有助于在一个或多个列中存储一些随机数据。


您可以根据需要复制/粘贴这些示例,以帮助您学习和实践SQL。

最后修改: 2025年01月28日 星期二 12:28