《EdgeDB 易经》 · 第十八章

# 以牙还牙​

Complex InsertsSchema CleanupTriggers

• 12 便士（最小单位的硬币）兑换一先令，

• 20 先令等于一磅，因此

• 每磅有 240 便士。

（还有一个 半便士铜币（halfpenny） 是一便士的一半，但这里我们就不在游戏中引入这么多细节了。）

Copy
```abstract type Currency {
required owner: Person;

required major: str;
required major_amount: int64 {
default := 0;
constraint min_value(0);
}

minor: str;
minor_amount: int64 {
default := 0;
constraint min_value(0);
}
minor_conversion: int64;

sub_minor: str;
sub_minor_amount: int64 {
default := 0;
constraint min_value(0);
}
sub_minor_conversion: int64;
}
```

Copy
```type Pound extending Currency {
default := 'pound'
}
default := 'shilling'
}
default := 20
}
default := 'pence'
}
default := 240
}
}
```

Copy
```insert Pound {
owner := (select Person filter .name = 'Count Dracula'),
major_amount := 2500,
minor_amount := 50,
sub_minor_amount := 200
};
```

Copy
```select Currency {
owner: {name},
total := .major_amount + (.minor_amount / .minor_conversion) + (.sub_minor_amount / .sub_minor_conversion)
};
```

```{default::Pound {owner: default::Vampire {name: 'Count Dracula'}, total: 2503.3333333333335}}
```

Copy
```std::round(value: int64) -> float64
std::round(value: float64) -> float64
std::round(value: bigint) -> bigint
std::round(value: decimal) -> decimal
std::round(value: decimal, d: int64) -> decimal
```

Copy
```select (for character in {'Jonathan Harker', 'Mina Murray', 'The innkeeper', 'Emil Sinclair'}
union (
insert Pound {
owner := assert_single((select Person filter .name = character)),
major_amount := <int64>round(random() * 500),
minor_amount := <int64>round(random() * 100),
sub_minor_amount := <int64>round(random() * 500)
})) {
owner: {
name
},
pounds := .major_amount,
shillings := .minor_amount,
pence := .sub_minor_amount,
total_pounds :=
round(<decimal>(.major_amount + (.minor_amount / .minor_conversion) + (.sub_minor_amount / .sub_minor_conversion)), 2)
};
```

```{
default::Pound {
owner: default::NPC {name: 'Jonathan Harker'},
pounds: 386,
shillings: 80,
pence: 184,
total_pounds: 390.77n,
},
default::Pound {
owner: default::NPC {name: 'Mina Murray'},
pounds: 385,
shillings: 57,
pence: 272,
total_pounds: 388.98n,
},
default::Pound {
owner: default::NPC {name: 'The innkeeper'},
pounds: 374,
shillings: 40,
pence: 187,
total_pounds: 376.78n,
},
default::Pound {
owner: default::PC {name: 'Emil Sinclair'},
pounds: 20,
shillings: 86,
pence: 1,
total_pounds: 24.30n,
},
}
```

（如果你不想看到 `decimal` 类型最后的 `n`，只需将其转换为 `<float32>``<float64>` 即可）

Copy
```type Dollar {
required dollars: int64;
required cents: int64;
property total_money := .dollars + (.cents / 100)
}
```

Copy
```select (100 + (55 / 100)) is float64;
```

Copy
```select (
insert Dollar {
dollars := 100,
cents := 55
}
) {
total_money
};
```

Copy
```insert City {
name := 'Munich',
};

insert City {
name := 'London',
};
```

Copy
```for city_name in {'Munich', 'London'}
union (
insert City {
name := city_name
}
);
```

Copy
```for country_name in {'Hungary', 'Romania', 'France', 'Slovakia'}
union (
insert Country {
name := country_name
}
);
```

Copy
```for city in {
('City 1\'s name', 'City 1\'s modern name', 800),
('City 2\'s name', 'City 2\'s modern name', 900),
('City 3\'s name', 'City 3\'s modern name', 455),
}
union (
insert City {
name := city.0,
modern_name := city.1,
population := city.2
}
);
```

Copy
```for n in {1, 2, 3, 4, 5}
union (
insert Crewman {
number := n,
first_appearance := cal::to_local_date(1893, 7, 6),
last_appearance := cal::to_local_date(1893, 7, 16),
}
);

insert Sailor {
name := 'The Captain',
rank := Rank.Captain
};

insert Sailor {
name := 'The First Mate',
rank := Rank.FirstMate
};

insert Sailor {
name := 'The Second Mate',
rank := Rank.SecondMate
};

insert Sailor {
name := 'The Cook',
rank := Rank.Cook
};

insert Ship {
name := 'The Demeter',
sailors := Sailor,
crew := Crewman
};
```

Copy
```insert Ship {
name := 'The Demeter',
sailors := {
(insert Sailor {
name := 'The Captain',
rank := Rank.Captain
}),
(insert Sailor {
name := 'The First Mate',
rank := Rank.FirstMate
}),
(insert Sailor {
name := 'The Second Mate',
rank := Rank.SecondMate
}),
(insert Sailor {
name := 'The Cook',
rank := Rank.Cook
})
},
crew := (
for n in {1, 2, 3, 4, 5}
union (
insert Crewman {
number := n,
first_appearance := cal::to_local_date(1893, 7, 6),
last_appearance := cal::to_local_date(1893, 7, 16),
}
)
)
};
```

→ 点击这里查看到第 18 章为止的所有代码

1. 在德古拉时代，德国的货币使用的是金马克（Goldmark）。一金马克是 100 芬尼（Pfennig）。你会如何制作这种货币类型？

查看答案
2. 尝试给上题中新增的类型添加两个注释（annotations）。其中一个称为 `description` 并说明 `One mark = 100 Pfennig`。另一个称为 `note`，并说明硬币的种类。

这里是硬币的种类：1, 2, 5, 10, 20, 25 芬尼（Pfennig）硬币。

查看答案
3. 一个名叫戈德布兰（Godbrand）的吸血鬼刚刚袭击了一个村庄，将三个村民变成了 `MinorVampire`。你将如何一次插入涉及到的所有（7个）对象？

下面是他们的数据（姓名、出生日期（`first_appearance`）、变成 MinorVampire 的日期（`last_appearance`））：

```('Fritz Frosch', '1850-01-15', '1893-09-11'),
('Levanta Sinyeva', '1862-02-24', '1893-09-11'),
('김훈', '1860-09-09', '1893-09-11'),
```
查看答案