美文网首页
[翻译]Sequel数据库模式修改方法

[翻译]Sequel数据库模式修改方法

作者: sladeliu | 来源:发表于2017-10-13 13:11 被阅读0次

    原文链接

    这是一个对常用的模式修改方法的简要描述:

    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类型,TrueClassFalseClass会被视为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则不允许NULL。如果为指定,则依照使用的数据库的默认情况
    :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_keyforeign_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_tableprimary_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_tableindex方法类似,add_index会给表创建新的索引:

    alter_table(:albums) do
      add_index :artist_id
    end
    

    该方法接受和create_tableindex方法一样的选项,用数组能创建多列索引:

    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_tablefull_text_indexspatial_index方法一样,这两个方法会为表创建相应的索引。

    add_constraint(添加约束)

    create_tableconstraint方法类似,这会为表添加一个命名的约束:

    alter_table(:albums) do
      add_constraint(:name_min_length){char_length(name) > 2}
    end
    

    注意,没有专门用来添加未命名约束的方法,不过你可以将nil作为add_constraint的第1个参数来达到相同的目的。当然,我们并不推荐这么做,因为删除未命名的约束是很困难的。

    add_unique_constraint(添加唯一约束)

    create_tableunique方法一样,为表添加唯一约束。

    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)
    

    相关文章

      网友评论

          本文标题:[翻译]Sequel数据库模式修改方法

          本文链接:https://www.haomeiwen.com/subject/vpdzyxtx.html