原文链接
这是一个对常用的模式修改方法的简要描述:
create_table(创建数据表)
create_table
是最常用的模式修改方法,它向模式中添加一个数据表。你提供一个符号类型的参数作为数据表的名字,类似下面的语句块:
create_table(:artists) do
primary_key :id
String :name
end
注意如果你想给数据表添加主键,你必须指定一个,Sequel默认是不会创建的。
列类型
当method_missing
调用column
时,create_table语句块中的大部分方法调用会创建数据列。通常情况下用具体的列类型作为方法名可以创建相应的列,方法名后紧跟的是用符号表示的列名,在列名后面还可以有一些选项。如果用Sequel能够识别的ruby类型作为方法名,Sequel会根据给定的数据库将其转换为恰当的类型。因此当你指定String
类型时,实际上Sequel会根据底层数据库而使用varchar或text类型。下面给出了所有能被Sequel转换成数据库类型:
许多能在create_table
块中调用的方法能创建
create_table(:columns_types) do # common database type used
Integer :a0 # integer
String :a1 # varchar(255)
String :a2, :size=>50 # varchar(50)
String :a3, :fixed=>true # char(255)
String :a4, :fixed=>true, :size=>50 # char(50)
String :a5, :text=>true # text
File :b, # blob
Fixnum :c # integer
Bignum :d # bigint
Float :e # double precision
BigDecimal :f # numeric
BigDecimal :f2, :size=>10 # numeric(10)
BigDecimal :f3, :size=>[10, 2] # numeric(10, 2)
Date :g # date
DateTime :h # timestamp
Time :i # timestamp
Time :i2, :only_time=>true # time
Numeric :j # numeric
TrueClass :k # boolean
FalseClass :l # boolean
end
注意,除了通过ruby的类型,Sequel还会通过列选项自动推断要使用哪种数据库数据类型。也同样需要注意,由于ruby中并没有Boolean
类型,TrueClass
或FalseClass
会被视为boolean
类型的列,你可以使用它们两个中的任意一个。
同时还需要注意这种转换只会对被Sequel支持的ruby类型起作用。所有其他的情况,Sequel会按照字面使用指定的类型:
create_table(:columns_types) do # database type used
string :a1 # string
datetime :a2 # datetime
blob :a3 # blob
inet :a4 # inet
end
除了将列类型作为方法名使用,你还可以使用column
方法,第二个参数是指定的数据类型,可以是ruby类型、符号或者字符串:
create_table(:columns_types) do # database type used
column :a1, :string # string
column :a2, String # varchar(255)
column :a3, 'string' # string
column :a4, :datetime # datetime
column :a5, DateTime # timestamp
column :a6, 'timestamp(6)' # timestamp(6)
end
列选项
当使用类型名作为方法名时,第3个参数可以使用一个可选的hash。当使用column
方法时,第4个参数是这个可选的hash。以下是被支持的选项:
选项 | 说明 |
---|---|
:default |
提供列的默认值 |
:index |
为列创建索引。如果给的是个hash,则使用该hash作为索引 |
:null |
标注该列是否能够使用NULL 空值。如果为true 则允许NULL ,如果为false 则不允许NUL L。如果为指定,则依照使用的数据库的默认情况 |
:unique |
标注该列是唯一的,通常情况下和对该列创建唯一索引有同样的效果 |
其他方法
除了column
方法和一些其他的创建列的方法,这里还有一些其他的方法可以使用:
primary_key(主键)
前面已经使用过这个方法了。该方法会创建一个integer
类型的自增的主键。
create_table(:a0){primary_key :id}
如果想要一个64位integer
自增主键,可以这样:
create_table(:a0){primary_key :id, :type=>Bignum}
如果不想创建一个integer
自增主键,那就不要用该方法。你应该在column
方法或相应类型的方法中使用:primary_key
选项:
create_table(:a1){Integer :id, :primary_key=>true} # Non autoincrementing integer primary key
create_table(:a2){String :name, :primary_key=>true} # varchar(255) primary key
如果想创建一个复合主键,那么你应该调用primary_key
方法并传递给它一个包含列符号名的数组:
create_table(:items) do
Integer :group_id
Integer :position
primary_key [:group_id, :position]
end
如果给primary_key
提供一个数组,它并不会创建一个列,而是设置一个主键约束。
foreign_key(外键)
foreign_key
被用来创建一个和另一个(也可以是同一个)数据表中的一个列相关联的外键列。该方法的第1个参数是列名,第2个参数是相关联的数据表,第3个参数是一个hash对,这是可选的。下面给一个简单的例子:
create_table(:albums) do
primary_key :id
foreign_key :artist_id, :artists
String :name
end
foreign_key
接受以下给定的选项:
选项 | 说明 |
---|---|
:deferrable |
使外键约束能延期校验,因此在事物结束前它不会被检验。 |
:key |
与作为外键的列相关联的关联表中的列。如果这个列引用的是关联表的主键,则这不是必须的,至少在大多数数据库是这样的。 |
:on_delete |
指定与外键列关联的记录的主键被删除时的行为。可以是:restrict 、:cascade 、:set_null 或者:set_default 。你也可以使用一个被逐字地使用的字符串。 |
:on_update |
指定与外键列关联的记录的主键被修改时的行为。和:on_delete 有一样的可选值。 |
和primary_key
一样,如果给foreign_key
提供一个数组,它并不会创建一个列,而是设置一个外键约束:
create_table(:artists) do
String :name
String :location
primary_key [:name, :location]
end
create_table(:albums) do
String :artist_name
String :artist_location
String :name
foreign_key [:artist_name, :artist_location], :artists
end
index(索引)
index为数据表创建索引。对单一列来说,调用index
方法和在创建列时使用:index
选项的效果一样:
create_table(:a){Integer :id, :index=>true}
# Same as:
create_table(:a) do
Integer :id
index :id
end
create_table(:a){Integer :id, :index=>{:unique=>true}}
# Same as:
create_table(:a) do
Integer :id
index :id, :unique=>true
end
和primary_key
与foreign_key
方法类似,调用index
方法并提供一个符号数组会创建一个多列索引:
create_table(:albums) do
primary_key :id
foreign_key :artist_id, :artists
Integer :position
index [:artist_id, :position]
end
index方法同样能接受一些可选项:
选项 | 说明 |
---|---|
:name |
索引名(如果未提供则根据表名和列名生成) |
:type |
索引使用的数据类型(部分数据库支持) |
:unique |
使索引唯一,不允许出现重复的值。 |
:where |
创建一个局部索引(部分数据库支持) |
unique(唯一索引)
unique
方法为数据表创建一个唯一约束。通常情况下,唯一约束和唯一索引运行起来是一样的。因此下面三个create_table
语句块的效果实际上是一样的:
create_table(:a){Integer :a, :unique=>true}
create_table(:a) do
Integer :a
index :a, :unique=>true
end
create_table(:a) do
Integer :a
unique :a
end
与index
类似,unique
方法可以设置一个多列唯一索引。多列唯一索引可以确保索引列中每个值组合都是唯一的:
create_table(:a) do
Integer :a
Integer :b
unique [:a, :b]
end
full_text_index and spatial_index(全文索引和局部索引)
只有部分数据库支持这两个能创建特殊索引类型的方法。它们和index
有一样的可选项。
constraint(约束)
constraint
方法会创建一个命名的表约束:
create_table(:artists) do
primary_key :id
String :name
constraint(:name_min_length){char_length(name) > 2}
end
不使用语句块,你还可以使用类似Dataset#where
作为方法的参数达到同样效果:
create_table(:artists) do
primary_key :id
String :name
constraint(:name_length_range, Sequel.function(:char_length, :name)=>3..50)
end
check(check约束)
check运行起来和constraint
很像,但是它没有名字,其创建的是一个未命名的约束:
create_table(:artists) do
primary_key :id
String :name
check{char_length(name) > 2}
end
create_join_table(创建连接表)
create_join_table
是一种快速地创建简单的多对多关系的连接表的方式:
create_join_table(:artist_id=>:artists, :album_id=>:albums)
上面的语句如果扩展开会是这样:
create_table(:albums_artists) do
foreign_key :album_id, :albums, :null=>false
foreign_key :artist_id, :artists, :null=>false
primary_key [:album_id, :artist_id]
index [:artist_id, :album_id]
end
create_table :as=>(创建表,带:as=>参数)
从SELECT
查询的结果创建表时,不给create_table
传一个语句块进去,而是提供一个数据集给:as选项:
create_table(:older_items, :as=>DB[:items].where{updated_at < Date.today << 6})
alter_table(修改表)
alter_table
被用来修改已存在的表。它能够修改表的列、索引、约束。就像使用create_table
一样,它接受一个instance_evaled
的语句块,并且有其自己的方法:
add_column(增加列)
最常用的方法之一,add_column用来给表增加列。这个API和create_table的column方法很像。它的第1个参数是列名,第2个参数是列数据类型,第3个参数是一个可选的hash:
alter_table(:albums) do
add_column :copies_sold, Integer, :default=>0
end
drop_column(丢弃列)
正如你期望的一样,drop_column
带一个参数,以此参数为列名的列会被丢弃。这个方法常常用在一个迁移的down
块中,用来丢弃在up
块中被添加的列:
alter_table(:albums) do
drop_column :copies_sold
end
rename_column(重命名列)
rename_column
用来重命名列。第1个参数是旧列名,第2个参数是新列名:
alter_table(:albums) do
rename_column :copies_sold, :total_sales
end
add_primary_key(添加主键)
如果你忘了给表添加一个主键,现在想加上,那你可以用add_primary_key
方法。这通常用来在真实模型中为关联表添加多对多关系:
alter_table(:albums_artists) do
add_primary_key :id
end
就像create_table
的primary_key
方法一样,如果你提供一个符号数组,Sequel不会添加一列,而是添加一个复合主键约束:
alter_table(:albums_artists) do
add_primary_key [:album_id, :artist_id]
end
如果仅仅是想把一个已经存在的单列变成主键,那么调用add_primary_key
时就给它一个只包含一个符号的数组:
alter_table(:artists) do
add_primary_key [:id]
end
add_foreign_key(添加外键)
add_foreign_key
用来给表添加新的外键列或外键约束。类似add_primary_key
,如果用一个符号作为第1个参数,该方法会创建一个新列:
alter_table(:albums) do
add_foreign_key :artist_id, :artists
end
如果想给一个已经存在的列添加外键约束,就提供给它一个只包含一个元素的数组:
alter_table(:albums) do
add_foreign_key [:artist_id], :artists
end
提供一个包含多列列名的符号的数组能够设置一个多列外键约束:
alter_table(:albums) do
add_foreign_key [:artist_name, :artist_location], :artists
end
add_index(添加索引)
跟create_table
的index
方法类似,add_index
会给表创建新的索引:
alter_table(:albums) do
add_index :artist_id
end
该方法接受和create_table
的index
方法一样的选项,用数组能创建多列索引:
alter_table(:albums_artists) do
add_index [:album_id, :artist_id], :unique=>true
end
drop_index(丢弃索引)
drop_index
会丢弃一个已存在的索引:
alter_table(:albums) do
drop_index :artist_id
end
与drop_column
一样,该方法通常会出现在迁移的down
块中。
用:name
选项能丢弃指定名字的索引:
alter_table(:albums) do
drop_index :artist_id, :name=>:artists_id_index
end
add_full_text_index, add_spatial_index(添加全文索引/添加局部索引)
与create_table
的full_text_index
和spatial_index
方法一样,这两个方法会为表创建相应的索引。
add_constraint(添加约束)
与create_table
的constraint
方法类似,这会为表添加一个命名的约束:
alter_table(:albums) do
add_constraint(:name_min_length){char_length(name) > 2}
end
注意,没有专门用来添加未命名约束的方法,不过你可以将nil
作为add_constraint
的第1个参数来达到相同的目的。当然,我们并不推荐这么做,因为删除未命名的约束是很困难的。
add_unique_constraint(添加唯一约束)
和create_table
的unique
方法一样,为表添加唯一约束。
alter_table(:albums) do
add_unique_constraint [:artist_id, :name]
end
drop_constraint(丢弃约束)
丢弃一个已命名的约束:
alter_table(:albums) do
drop_constraint(:name_min_length)
end
没有单独的丢弃未命名约束的方法。通常,数据库会自动给未命名约束一个名字,你要做的就是找出这个名字。因此你不应该让一个你将来可能会丢弃的约束成为未命名约束。
有些数据库可能还要求你必须指定约束的类型,这可以通过:type
选项来完成:
alter_table(:albums) do
drop_constraint(:albums_pk, :type=>:primary_key)
drop_constraint(:albums_fk, :type=>:foreign_key)
drop_constraint(:albums_uk, :type=>:unique)
end
set_column_default(设置列的默认值)
该方法会改变指定列的默认值:
alter_table(:albums) do
set_column_default :copies_sold, 0
end
set_column_type(设置列的数据类型)
该方法会改变列的数据类型,大多数数据库会尝试自动转换已经存在的数据值到新的类型:
alter_table(:albums) do
set_column_type :copies_sold, Bignum
end
你可以用字符串或符号指定类型,这时会按字面指定数据类型。或者使用被支持的ruby类型,这是会转为恰当的数据库数据类型。
set_column_allow_null(设置列允许空值)
该方法改变列是否允许空值:
alter_table(:albums) do
set_column_allow_null :artist_id, true # NULL
set_column_allow_null :copies_sold, false # NOT NULL
end
其他修改数据库模式的方法
Sequel::Database
有很多关于模式修改的实例方法,其中大多数是与alter_table
中的方法作用类似的“快捷方法”。下面列出的Database的实例方法其实只是调用了alter_table
中的同名函数,并将表名作为第1个参数,其余参数放在表名之后:
add_column
drop_column
rename_column
add_index
drop_index
set_column_default
set_column_type
举例来说,下面两个方法执行效果相同:
alter_table(:artists){add_column :copies_sold, Integer}
add_column :artists, :copies_sold, Integer
还有一些不和alter_table
类似的模式修改方法:
drop_table
drop_table
可以带很多参数,它将这些参数都视为表名,这些表将被丢弃:
drop_table(:albums_artists, :albums, :artists)
注意,如果你使用了外键,而数据库要确保引用完整性,这时要按特定的顺序丢弃这些表。通常你要先丢弃包含外键的表,然后再丢弃被这些表引用主键的表。
drop_table?
和drop_table
类似,但仅当表不存在时drop_table?
才会丢弃表。有些数据库会使用IF NOT EXISTS
检测表是否存在,其他的数据库则使用单独的查询语句来检测。
不要在迁移中使用该方法,如果该表不存在,这样做会破坏迁移。
rename_table
你可以使用rename_table
重命名一个表。类似rename_column
,第1个参数是当前名,第2个参数是新名:
rename_table(:artist, :artists)
create_table!
create_table!
在创建表之前会试图丢弃已存在的同名表,因此:
create_table!(:artists) do
primary_key :id
end
和下载的代码作用一样:
drop_table?(:artists)
create_table(:artists) do
primary_key :id
end
不要在迁移中使用该方法,如果该表不存在,这样做会破坏迁移。
create_table?
create_table?
仅仅当表不存在时才会将其创建,因此:
create_table?(:artists) do
primary_key :id
end
和下面的代码作用一样:
unless table_exists?(:artists)
create_table(:artists) do
primary_key :id
end
end
和create_table!
一样,它不能被用在迁移里。
create_view 和 create_or_replace_view(创建视图/创建或替换视图)
该组方法用来创建视图。两者的区别是create_or_replace_view
会无条件地替换已存在的同名视图。而create_view
则会抛出一个错误。两个方法接受同样的参数,第1个参数是视图名,第2个参数是一个字符串或者一个数据集:
create_view(:gold_albums, DB[:albums].where{copies_sold > 500000})
create_or_replace_view(:gold_albums, "SELECT * FROM albums WHERE copies_sold > 500000")
drop_view(删除视图)
drop_view
删除一个已存在的视图。和drop_table
类似,它可以接受多参数:
drop_view(:gold_albums, :platinum_albums)