sql脚本导入sql
I can hardly imagine making any complex database changes without using SQL scripts. We actually used them in this series so far, but we haven’t pointed out what they actually are. Today we’ll stand up against that injustice. Sit back, relax, and get ready to learn something new and useful.
我几乎无法想象不使用SQL脚本就进行任何复杂的数据库更改。 到目前为止,我们在本系列中实际上已经使用了它们,但是我们没有指出它们的实际含义。 今天,我们将反对这种不公正。 坐下来,放松,并准备学习新的有用的东西。
(Desired changes)
Before we do anything else, we’ll describe what we have and what we want to achieve. This is not specific for databases only, but for almost any process – you should give yourself some time to think about the problem before you start coding/digging.
在执行其他任何操作之前,我们将描述我们拥有的以及我们想要实现的目标。 这不仅是特定于数据库的,而且几乎针对所有过程-在开始编码/挖掘之前,您应该给自己一些时间来思考问题。
In the picture below, you can see our current data model. Tables country and city serve as storage where we’ll store data related to countries in cities. Unless our database serves only that purpose, this model is not too “smart”. I guess you want to have something more than just a list of countries and cities in your database:
在下面的图片中,您可以看到我们当前的数据模型。 国家和城市表用作存储,我们将在其中存储与城市中的国家/地区有关的数据。 除非我们的数据库仅用于此目的,否则该模型不会太“聪明”。 我想您想拥有的不仅仅是数据库中的国家和城市列表:
This model served its’ purpose so far, but now we’re ready to move to the next level and we need something more complex. While we’ll need these two tables to store countries and cities, we’ll add a few more tables.
到目前为止,该模型已达到其目的,但现在我们准备移至下一个级别,我们需要更复杂的东西。 虽然我们需要这两个表来存储国家和城市,但我们还要添加一些表。
- Tip:提示:
Now we have the data model with 6 tables. New tables are:
现在我们有了包含6个表的数据模型。 新表是:
- employee – Contains a list of all employees in our company 员工 –包含我们公司所有员工的列表
- customer – Contains a list of all customers we’ve worked with 客户 –包含我们合作过的所有客户的列表
- call_outcome – Is a list of all possible ways any call could finish. Tables like this one are usually called dictionaries (catalogs). They are specific because values stored here almost never change and business logic is often directly related to these values. For example, call outcome could be “Call successful – sales” or “Customer rejected our offer” call_outcome –是所有呼叫可以完成的所有可能方式的列表。 像这样的表通常称为字典(目录)。 它们之所以特别,是因为这里存储的值几乎永远不变,并且业务逻辑通常与这些值直接相关。 例如,致电结果可能是“致电成功–销售”或“客户拒绝了我们的报价”
- call – Contains details about calls employees had with customers. Please notice that in this table employees, customers and call outcomes are related 通话 -包含有关员工与客户通话的详细信息。 请注意,在此表中,员工,客户和通话结果是相关的
These 4 tables are much more than just a place to store the data in the way we did that with counties and cities. While everything in databases is closely related to our business, these 4 new tables are much more specific than the 2 ones we already had. Basically, they give the purpose to the whole data model.
这4个表不仅是存储数据的地方,而且以与县和城市相同的方式存储数据。 尽管数据库中的所有内容都与我们的业务紧密相关,但是这四个新表比我们已经拥有的两个表更加具体。 基本上,它们为整个数据模型提供了目的。
Now we know where we are and where we want to be. The only thing we miss is how to get there. To get there we’ll use the SQL script. But before we do that, let’s see what the SQL script really is.
现在我们知道我们在哪里以及我们想要在哪里。 我们唯一想念的是如何到达那里。 为了到达那里,我们将使用SQL脚本。 但是在执行此操作之前,让我们看看SQL脚本的真正含义。
(SQL Script)
In programming, scripts are the series of commands (sequence of instructions) or a program that will be executed in another program rather than by the computer processor (compiled programs are executed by computer processor –> please notice that the script is not compiled).
在编程中,脚本是一系列命令(指令序列)或将在另一个程序中而不是由计算机处理器执行的程序(已编译的程序由计算机处理器执行->请注意,脚本未编译)。
Same stands for SQL scripts. The only thing that is specific is that commands in such scripts are SQL commands. And these commands could be any combination of DDL (Data Definition Language) or DML (Data Manipulation Language) commands. Therefore, you could change the database structure (CREATE, ALTER, DROP objects) and/or change the data (perform INSERT/UPDATE/DELETE commands).
相同代表SQL脚本。 唯一具体的是此类脚本中的命令是SQL命令。 这些命令可以是DDL(数据定义语言)或DML(数据操作语言)命令的任意组合。 因此,您可以更改数据库结构(CREATE,ALTER,DROP对象)和/或更改数据(执行INSERT / UPDATE / DELETE命令)。
It’s desired that you use scripts, especially when you’re deploying a new version and you want to keep current data as they were before that change.
希望您使用脚本,尤其是在部署新版本时,并且想要保持当前数据在更改前保持不变。
(Backup and restore)
Using scripts is usually related to making significant changes in the database. I might be paranoid about this, but I prefer to backup the database before these changes.
使用脚本通常与对数据库进行重大更改有关。 我对此可能有点偏执,但是我更喜欢在这些更改之前备份数据库。
- Tip: If you expect major changes in your databases, either in structure, either data changes, creating a backup is always a good idea. You could backup the entire database or only 1 table. That’s completely up to you and the changes you’re making. 提示:如果您希望数据库发生重大变化,无论是结构上还是数据上的变化,创建备份始终是一个好主意。 您可以备份整个数据库或仅备份一个表。 这完全取决于您和您所做的更改。
Oldie but goodie: “There are two types of people: 1. People who do backup & 2. People who will start doing backup.”
老歌但又好吃: “有两种类型的人:1.做备份的人和2.将开始做备份的人。”
In SQL Server you can easily backup the whole database. First right-click on the database you want to backup, go to Tasks, and choose the Back Up option:
在SQL Server中,您可以轻松备份整个数据库。 首先,右键单击要备份的数据库,转到“ 任务” ,然后选择“ 备份”选项:
After choosing the backup option, you’ll get the pop-up as on the picture below:
选择备份选项后,您将获得如下图所示的弹出窗口:
Click OK, and your backup is created. Now we can create a copy of our database. We’ll do that by restoring from the backup. To do that, follow the process in the picture below:
单击“ 确定” ,您的备份已创建。 现在,我们可以创建数据库的副本。 我们将通过从备份还原来做到这一点。 为此,请按照以下图片中的过程进行操作:
You’ll need to enter the name of the restored database (our_first_database_old) and click OK:
您需要输入恢复的数据库的名称( our_first_database_old ),然后单击OK :
The result of these actions shall be that now we have 2 identical databases – our_first_database & our_first_database_old. We’ll use the first one as the one where we’ll run our SQL script. In case we would screw something up, we could always easily revert changes using our backup.
这些操作的结果将是现在我们有了2个相同的数据库– our_first_database和our_first_database_old 。 我们将使用第一个脚本来运行SQL脚本。 万一我们搞砸了,我们总是可以使用备份轻松地还原更改。
(SQL Script – example)
Now we’re ready to take a look at our script. We want to do two different things:
现在我们准备看一下脚本。 我们想做两件事:
Of course, we’ll run DDL commands first and then run DML commands. Trying to insert data into a table that doesn’t exist would result in errors. So, let’s take a look at our script now:
当然,我们将先运行DDL命令,然后再运行DML命令。 尝试将数据插入不存在的表中会导致错误。 现在,让我们看一下我们的脚本:
-- tables
-- Table: call
CREATE TABLE call (
id int NOT NULL IDENTITY(1, 1),
employee_id int NOT NULL,
customer_id int NOT NULL,
start_time datetime NOT NULL,
end_time datetime NULL,
call_outcome_id int NULL,
CONSTRAINT call_ak_1 UNIQUE (employee_id, start_time),
CONSTRAINT call_pk PRIMARY KEY (id)
);
-- Table: call_outcome
CREATE TABLE call_outcome (
id int NOT NULL IDENTITY(1, 1),
outcome_text char(128) NOT NULL,
CONSTRAINT call_outcome_ak_1 UNIQUE (outcome_text),
CONSTRAINT call_outcome_pk PRIMARY KEY (id)
);
-- Table: customer
CREATE TABLE customer (
id int NOT NULL IDENTITY(1, 1),
customer_name varchar(255) NOT NULL,
city_id int NOT NULL,
customer_address varchar(255) NOT NULL,
next_call_date date NULL,
ts_inserted datetime NOT NULL,
CONSTRAINT customer_pk PRIMARY KEY (id)
);
-- Table: employee
CREATE TABLE employee (
id int NOT NULL IDENTITY(1, 1),
first_name varchar(255) NOT NULL,
last_name varchar(255) NOT NULL,
CONSTRAINT employee_pk PRIMARY KEY (id)
);
-- foreign keys
-- Reference: call_call_outcome (table: call)
ALTER TABLE call ADD CONSTRAINT call_call_outcome
FOREIGN KEY (call_outcome_id)
REFERENCES call_outcome (id);
-- Reference: call_customer (table: call)
ALTER TABLE call ADD CONSTRAINT call_customer
FOREIGN KEY (customer_id)
REFERENCES customer (id);
-- Reference: call_employee (table: call)
ALTER TABLE call ADD CONSTRAINT call_employee
FOREIGN KEY (employee_id)
REFERENCES employee (id);
-- Reference: customer_city (table: customer)
ALTER TABLE customer ADD CONSTRAINT customer_city
FOREIGN KEY (city_id)
REFERENCES city (id);
-- insert values
INSERT INTO call_outcome (outcome_text) VALUES ('call started');
INSERT INTO call_outcome (outcome_text) VALUES ('finished - successfully');
INSERT INTO call_outcome (outcome_text) VALUES ('finished - unsuccessfully');
INSERT INTO employee (first_name, last_name) VALUES ('Thomas (Neo)', 'Anderson');
INSERT INTO employee (first_name, last_name) VALUES ('Agent', 'Smith');
INSERT INTO customer (customer_name, city_id, customer_address, next_call_date, ts_inserted) VALUES ('Jewelry Store', 4, 'Long Street 120', '2020/1/21', '2020/1/9 14:1:20');
INSERT INTO customer (customer_name, city_id, customer_address, next_call_date, ts_inserted) VALUES ('Bakery', 1, 'Kurfürstendamm 25', '2020/2/21', '2020/1/9 17:52:15');
INSERT INTO customer (customer_name, city_id, customer_address, next_call_date, ts_inserted) VALUES ('Café', 1, 'Tauentzienstraße 44', '2020/1/21', '2020/1/10 8:2:49');
INSERT INTO customer (customer_name, city_id, customer_address, next_call_date, ts_inserted) VALUES ('Restaurant', 3, 'Ulica lipa 15', '2020/1/21', '2020/1/10 9:20:21');
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 4, '2020/1/11 9:0:15', '2020/1/11 9:12:22', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 2, '2020/1/11 9:14:50', '2020/1/11 9:20:1', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (2, 3, '2020/1/11 9:2:20', '2020/1/11 9:18:5', 3);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 1, '2020/1/11 9:24:15', '2020/1/11 9:25:5', 3);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 3, '2020/1/11 9:26:23', '2020/1/11 9:33:45', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 2, '2020/1/11 9:40:31', '2020/1/11 9:42:32', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (2, 4, '2020/1/11 9:41:17', '2020/1/11 9:45:21', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (1, 1, '2020/1/11 9:42:32', '2020/1/11 9:46:53', 3);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (2, 1, '2020/1/11 9:46:0', '2020/1/11 9:48:2', 2);
INSERT INTO call (employee_id, customer_id, start_time, end_time, call_outcome_id) VALUES (2, 2, '2020/1/11 9:50:12', '2020/1/11 9:55:35', 2);
Our script is a series of CREATE TABLE commands (creating 4 new tables), ALTER TABLE commands (adding foreign keys to these tables) and INSERT INTO commands (populating tables with the data). For INSERT commands, I’ve once more used Excel to create commands from the set of values:
我们的脚本是一系列CREATE TABLE命令(创建4个新表),ALTER TABLE命令(向这些表添加外键)和INSERT INTO命令(用数据填充表)。 对于INSERT命令,我再次使用Excel从值集中创建命令:
Everything should go smoothly and you should see this under “Messages” (a lot of (1 row affected messages)) as well the message “Query executed successfully” (and everything shall be green). In case something wouldn’t be OK, you’ll notice that 🙂
一切应该顺利进行,您应该在“消息” (很多(1行受影响的消息))下看到此消息,并看到消息“查询已成功执行” (并且所有消息应为绿色)。 如果出现问题,您会注意到
On the other hand, in the database list, when you expand our_first_database tables, you should see all the new tables. Now, we’re sure that we have new objects (tables) in our database. But what about the data? We’ll check the contents of these tables with simple SELECT statements.
另一方面,在数据库列表中,展开our_first_database表时,应该看到所有新表。 现在,我们确定数据库中有新的对象(表)。 但是数据呢? 我们将使用简单的SELECT语句检查这些表的内容。
(SQL Script – Comment)
As you’ve seen, in our SQL script we’ve combined DDL and DML commands. That will usually be the case when you’re deploying the new version of the database on the system that is currently live. You can’t simply delete everything and create new objects (tables & relations) because you would lose existing data and nobody really wants that (losing the data is probably the worst thing you could do about databases). Therefore, you’ll need to create a script that performs changes and inserts new data (usually data for new dictionaries).
如您所见,在我们SQL脚本中,我们结合了DDL和DML命令。 当您在当前处于活动状态的系统上部署数据库的新版本时,通常就是这种情况。 您不能简单地删除所有内容并创建新的对象(表和关系),因为您将丢失现有数据,而没有人真正想要它(丢失数据可能是您对数据库最糟糕的事情)。 因此,您需要创建一个脚本来执行更改并插入新数据(通常是新词典的数据)。
In our script, we’ve only created new objects and inserted data. All other commands are also allowed. For example, you could alter the existing table (adding or removing columns, adding properties) or even delete the table if it’s not needed anymore. Same stands for the data. You could perform not only INSERTs but also UPDATEs and DELETEs. In case you need to do that, you’ll make changes to the existing logic, so double-check everything (even things that you’ve already double-checked).
在脚本中,我们仅创建了新对象并插入了数据。 还允许所有其他命令。 例如,您可以更改现有表(添加或删除列,添加属性),或者如果不再需要该表,甚至可以删除该表。 相同代表数据。 您不仅可以执行INSERT,还可以执行UPDATE和DELETE。 如果需要这样做,您将对现有逻辑进行更改,因此请仔细检查所有内容(即使您已经仔细检查过的内容)。
(Conclusion)
We can conclude that we achieved what we initially planned. This is great because now we have a much more sophisticated (but still very simple) model we can use to write more complex queries than we did so far. I won’t go into the nature of relations in this article. That shall be covered in the upcoming article, so stay tuned.
我们可以得出结论,我们实现了最初计划的目标。 之所以这么棒,是因为现在我们有了一个比以前复杂得多(但仍然非常简单)的模型来编写更复杂的查询。 在本文中,我不会介绍关系的本质。 那将在下一篇文章中介绍,请继续关注。