校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > golang Gorm與數據庫完整性約束詳解

golang Gorm與數據庫完整性約束詳解

熱門標簽:地圖標注免費定制店 重慶慶云企業400電話到哪申請 不封卡外呼系統 寧波語音外呼系統公司 仙桃400電話辦理 湛江crm外呼系統排名 上海極信防封電銷卡價格 宿遷便宜外呼系統代理商 鄭州智能語音電銷機器人價格

數據庫約束要點:

主鍵約束(非空且唯一)外鍵約束 子表外鍵字段的值必須在主表被參照字段值得范圍內,或者為NULL;外鍵參照的必須是主表的主鍵或唯一鍵;主表主鍵/唯一鍵被子表參照時,主表相應記錄不允許被刪除

在golang中,采用orm對數據庫進行建模是比較方便的。grom是其中一個比較流行的orm工具。

本篇基于golang、grom1.91、和PostgreSQL來進行說明。

注:本文的例子是極端情況,一般情況只是單字段主鍵。

1、實體完整性:

每個關系(表)有且僅有一個主鍵,每一個主鍵值必須唯一,而且不允許為“空”(NULL)或重復。

type Product struct {
Code string `gorm:"primary_key"`
Price uint
UserID uint //`sql:"type:bigint REFERENCES users(id) on update no action on delete cascade"`
UserCode string //`sql:"type:bigint REFERENCES users(code) on update no action on delete cascade"`
User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`
gorm.Model
}

在利用gorm的db對象創建表,其使用的SQL如下:

CREATE TABLE public.products
(
 code text COLLATE pg_catalog."default" NOT NULL,
 price integer,
 user_id integer,
 user_code text COLLATE pg_catalog."default",
 id integer NOT NULL DEFAULT nextval('products_id_seq'::regclass),
 created_at timestamp with time zone,
 updated_at timestamp with time zone,
 deleted_at timestamp with time zone,
 CONSTRAINT products_pkey PRIMARY KEY (code, id)
)
WITH (
 OIDS = FALSE
)
TABLESPACE pg_default; 
ALTER TABLE public.products
 OWNER to postgres; 
 
-- Index: idx_products_deleted_at 
 
-- DROP INDEX public.idx_products_deleted_at; 
 
CREATE INDEX idx_products_deleted_at
 ON public.products USING btree
 (deleted_at)
 TABLESPACE pg_default;

說明:

1.1、grom.Model是gorm預定義的結構,用于實現軟刪除,定義如下:

type Model struct {
 ID uint `gorm:"primary_key"`
 CreatedAt time.Time
 UpdatedAt time.Time
 DeletedAt *time.Time `sql:"index"`
}

它里面已經定義了主鍵,在本例中,我們還定義了一個主鍵:

Code string `gorm:"primary_key"`

從SQL輸出我們看到:

CONSTRAINT products_pkey PRIMARY KEY (code, id)

因此,Gorm實現了完全的實體完整性支持,即可以支持字段主鍵,也可以支持聯合主鍵。

1.2、對比結構體和sql語句可以看出

1.2.1 表名=結構體名小寫的復數 例子:Product變為 products

1.2.2 字段名=結構體成員名大寫分隔的子串小寫形式用下劃線連接 例子:ID變為id CreatedAt變為created_at

1.3、前述1.1和1.2構成了Gorm的convention,它的文檔里有,默認情況下,就是這么處理,但是用戶可以不用gorm.Model,自定義表名、字段名,都可以支持。

2、域完整性:

是指數據庫表中的列必須滿足某種特定的數據類型或約束,又叫用戶定義完整性。包括:字段類型、值域、小數位數、CHECK、FOREIGN KEY 約束和DEFAULT、 NOT NULL。它們有的定義在字段上,有的定義在表上。例如:FOREIGN KEY 約束在PostgresSQL中,就是在表級別定義的;而,字段類型、長度、小數位數就是在字段上定義的。

2.1 通過結構體tag

`gorm:"xxx"` ,在字段上可以使用:type、size、precision、not null、default,Gorm就可以完成這些域完整性的定義

2.2 FOREIGN KEY 約束

2.2.1 單字段外鍵約束

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
 UserID uint //`sql:"type:bigint REFERENCES users(id) on update no action on delete cascade"`
  //UserCode string //`sql:"type:bigint REFERENCES users(code) on update no action on delete cascade"`
 User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
}
type User struct {
  //Code string `gorm:"primary_key"`
 Name string
 gorm.Model
  //Product Product //`gorm:"EMBEDDED"`
}

上面的代碼按照gorm文檔,創建了一個products belongs to user關系。執行的sql是:

CREATE TABLE "users" ("code" text,"name" text,"id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone , PRIMARY KEY ("code","id"))
CREATE TABLE "users" ("code" text,"name" text,"id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone , PRIMARY KEY ("code","id"))

我們看到,gorm沒有添加任何約束。按照Gorm文檔,這就是belongs to標準定義。

它不添加外鍵約束。

那么,改為顯式標準的形式,采用foreignkey tag呢?

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
 UserID uint //`sql:"type:integer REFERENCES users(id)`// on update no action on delete cascade"`
  //UserCode string //`sql:"type:bigint REFERENCES users(code) on update no action on delete cascade"`
  //UserID uint
 User User `gorm:"foreignkey:UserID;association_foreignkey:ID"` //`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
}
type User struct {
  //Code string `gorm:"primary_key"`
 Name string
 gorm.Model
  //Product Product //`gorm:"EMBEDDED"`
}

執行的sql是:

CREATE TABLE "users" ("name" text,"id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone , PRIMARY KEY ("id")) 
CREATE TABLE "products" ("code" text,"price" integer,"user_id" integer,"id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone , PRIMARY KEY ("id")) 

也沒有添加任何外鍵約束。

因此,gorm tag 的 foreignkey 和 association_foreignkey并不會添加外鍵約束。

但是,我們可以用sql tag來添加外鍵約束?。?!如下:

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
 UserID uint `sql:"type:integer REFERENCES users(id) on update no action on delete no action"`
  //UserCode string //`sql:"type:bigint REFERENCES users(code) on update no action on delete cascade"`
  //UserID uint
 User User `gorm:"foreignkey:UserID;association_foreignkey:ID"` //`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
}
type User struct {
  //Code string `gorm:"primary_key"`
 Name string
 gorm.Model
  //Product Product //`gorm:"EMBEDDED"`
}

創建products表的語句:

 CREATE TABLE "products" ("code" text,"price" integer,"user_id" integer REFERENCES users(id) on update no action on delete no action,"id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone , PRIMARY KEY ("id"))

注意,當使用sql tag時,不像gorm tag,它要你用數據庫表名和字段名,而gorm就只需要你使用結構體和其成員名即可。

外鍵被定義了,此時,可以滿足外鍵約束,如前述,具體是:

子表外鍵字段的值必須在主表被參照字段值得范圍內,或者為NULL;外鍵參照的必須是主表的主鍵或唯一鍵;主表主鍵/唯一鍵被子表參照時,主表相應記錄不允許被刪除

此時外鍵約束的名字是數據庫自己取的,可能長了,你可以自定義:

UserID uint `sql:"type:integer constraint ref REFERENCES users(id) on update no action on delete no action"`

加上 constraint xxx,就可以為約束取名為xx了。

上述外鍵約束是在定義結構體時,在結構體成員上定義的,因此翻譯為sql語句就變成了對字段的外鍵約束,那如果要定義參照聯合主鍵之類的外鍵呢?就不能在結構體中定義,而要使用gorm的api了。

2.2.2 多字段外鍵約束

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
  //UserID uint `sql:"type:integer REFERENCES users(id) on update no action on delete no action"`
  //UserCode string //`sql:"type:bigint REFERENCES users(code) on update no action on delete cascade"`
 UserCode string
 UserID uint
 User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`//`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
}
type User struct {
 Code string `gorm:"primary_key"`
 Name string
 gorm.Model
  //Product Product //`gorm:"EMBEDDED"`
}

在程序中使用:

postgres. Model( Product{}). AddForeignKey( "user_id,user_code", "users(id,code)", "no action", "no action")

這樣,products表就有約束:

CONSTRAINT products_user_id_user_code_users_id_code_foreign FOREIGN KEY (user_code, user_id)
REFERENCES public.users (code, id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION

如此就OK了。這里約束的名字就很長了,api沒有給你自己取名字的機會。

2.3 check約束

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
 UserID uint `sql:"type:integer check(code!='')"`
 UserCode string //`sql:"type:bigint constraint ref REFERENCES users(code) on update no action on delete cascade"`
  //UserCode string
  //UserID uint
 User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`//`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
}

這樣就行??雌饋磉@個check和userID沒有什么關系,是的,check會被定義到表上:

ALTER TABLE public.products

ADD CONSTRAINT products CHECK (code > ''::text);

因此,Check也完美了,找個結構體的字段,然后加上check就行了。

3、參照完整性:

對于永久關系的相關表,在更新、插入或刪除記錄時,如果只改其一,就會影響數據的完整性。對于更新、插入或刪除表間數據的完整性,統稱為參照完整性。

對于外鍵約束,插入參照完整性被滿足。因此,如前述:

UserID uint `sql:"type:integer REFERENCES users(id) on update no action on delete no action"`

定義好on update 和 on delete的參數,就可以滿足參照完整性。

具體改為:

UserID uint `sql:"type:integer REFERENCES users(id) on update cascade on delete cascade"`

即可,而且數據庫還允許有別的選擇,這里是級聯更新和級聯刪除,主表已刪除,子表就跟著刪,這是數據庫參照完整性的原初定義。

ps. gorm不默認實施參照完整性,不加約束的原因查了其git issue,主要是因為postgresql要求被關聯的表要先存在。而這會導致創建表和自動升級表migration的順序依賴,所以用戶要sqltag或者調用api手動實施。

4、*1對多 和 多對多關系

這不屬于完整性范疇。

4.1 1對多

1對多不需要實施完整性約束,因為用戶可以對應0到多個產品。因此,表結構里無需添加額外的約束。

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
  //UserID uint `sql:"type:integer constraint ref REFERENCES users(id) on update no action on delete no action check(code!='')"`
  //UserCode string //`sql:"type:bigint constraint ref REFERENCES users(code) on update no action on delete cascade"`
  //UserCode string
  //UserID uint
  //User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`//`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
 UserID uint
}
type User struct {
 Code string //`gorm:"primary_key"`
 Name string
 gorm.Model
 Products []Product
  //Product Product //`gorm:"EMBEDDED"`
}

上面是gorm一對多的典型定義,users表不會多任何字段,product表會多user_id字段。這里UserID是外鍵。也可以顯式定義,foreignkey 和Association ForeignKey 上例相當于:

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
  //UserID uint `sql:"type:integer constraint ref REFERENCES users(id) on update no action on delete no action check(code!='')"`
  //UserCode string //`sql:"type:bigint constraint ref REFERENCES users(code) on update no action on delete cascade"`
  //UserCode string
  //UserID uint
  //User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`//`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
 UserID uint
}
type User struct {
 Code string //`gorm:"primary_key"`
 Name string
 gorm.Model
 Products []Product `gorm:"foreignkey:UserID"`
  //Product Product //`gorm:"EMBEDDED"`
}

4.2 多對多

在關系型數據庫中,多對多關系需要多一張表,總共3張表,完整性grom是如何保證的?

type Product struct {
 Code string //`gorm:"primary_key"`
 Price uint
  //UserID uint `sql:"type:integer constraint ref REFERENCES users(id) on update no action on delete no action check(code!='')"`
  //UserCode string //`sql:"type:bigint constraint ref REFERENCES users(code) on update no action on delete cascade"`
  //UserCode string
  //UserID uint
  //User User //`gorm:"foreignkey:UserID;association_foreignkey:ID"`//`gorm:"foreignkey:UserID;association_foreignkey:ID"`
 gorm.Model
  //UserID uint
}
type User struct {
 Code string //`gorm:"primary_key"`
 Name string
 gorm.Model
 Products []Product `gorm:"many2many:user_language"`
  //Product Product //`gorm:"EMBEDDED"`
}

此時,會多一個表(jointtable連接表):

CREATE TABLE "user_language" ("user_id" integer,"product_id" integer, PRIMARY KEY ("user_id","product_id"))

products和users表的主鍵,被聯合作為新表的主鍵。在新表中,user_id和product_id也是外鍵,在Gorm中,是可以在many2many關系中自定義外鍵、關聯外鍵的。當然,外鍵約束就不要想了。

那么,在上例中,按照grom的語法,對于Products成員,外鍵和關聯外鍵分別是什么呢?簡言之,在gorm所有情況下,將嵌入結構體和其父結構體關聯起來的那個字段,就是外鍵;關聯外鍵是寫入外鍵的值的來源對應的鍵,通常就是父結構體的主鍵。在多對多情況下,如上例,連接表的user_id是外鍵,而寫入時,并沒有將user_id寫入Products []Product,寫入的是product_id代表的數據,因此product_id是associate_foreignkey,這是gorm的約定,很費解,解釋也牽強。

下面是多對多自引用:

type User struct {
 gorm.Model
 Friends []*User `gorm:"many2many:friendships;association_jointable_foreignkey:friend_id"`
}

用association_jointable_foreignkey在連接表里創建了一個字段。也比較費解。

綜上:

1、字段的基本約束,通過gorm tag基本都可以設置。

2、gorm支持實體完整性約束。

3、域完整性約束中,外鍵約束需要通過 sql tag或調用api實現,check約束可以直接在字段上定義。

4、參照完整性gorm不能默認實現,必須通過sql tag或者調用api實現。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • gorm update傳入struct對象,零值字段不更新的解決方案
  • gorm操作MySql數據庫的方法
  • Go基于GORM 獲取當前請求所執行的 SQL 信息(思路詳解)
  • Golang 使用gorm添加數據庫排他鎖,for update
  • golang gorm 結構體的表字段缺省值設置方式
  • golang gorm 計算字段和獲取sum()值的實現
  • gorm FirstOrCreate和受影響的行數實例
  • 解決Go gorm踩過的坑

標簽:安康 儋州 物業服務 海南 西雙版納 電子產品 遼寧 青海

巨人網絡通訊聲明:本文標題《golang Gorm與數據庫完整性約束詳解》,本文關鍵詞  golang,Gorm,與,數據庫,完整性,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《golang Gorm與數據庫完整性約束詳解》相關的同類信息!
  • 本頁收集關于golang Gorm與數據庫完整性約束詳解的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    青青草伊人久久| 欧美伊人久久大香线蕉综合69| 91网站黄www| 日韩欧美国产一区二区三区 | 不卡视频免费播放| 欧美日韩视频在线一区二区| 国产精品视频看| 麻豆91在线播放免费| 欧洲一区在线电影| 日韩一区日韩二区| 国产精品综合久久| 欧美一区二区三区免费| 亚洲一区二区三区爽爽爽爽爽 | 久久影院视频免费| 午夜精品国产更新| 色88888久久久久久影院按摩 | 日韩免费一区二区| 亚洲综合成人网| 色综合久久久久久久| 国产精品久久三区| 丁香啪啪综合成人亚洲小说 | 狠狠久久亚洲欧美| 欧美一级生活片| 午夜亚洲国产au精品一区二区| 97精品久久久久中文字幕 | 午夜电影一区二区三区| 欧美影视一区在线| 亚洲亚洲精品在线观看| 91黄色免费看| 亚洲一区二区视频在线| 欧美私模裸体表演在线观看| 亚洲欧美欧美一区二区三区| 91网站在线观看视频| 亚洲欧美国产77777| 91免费观看在线| 一区二区三区四区视频精品免费 | 秋霞午夜av一区二区三区| 91麻豆精品国产91久久久资源速度| 一区二区三区中文字幕精品精品| 色菇凉天天综合网| 婷婷综合五月天| 日韩美女视频一区二区在线观看| 日本亚洲电影天堂| 久久一日本道色综合| 成人免费va视频| 亚洲女人的天堂| 欧美二区三区91| 久久精品99国产国产精| 欧美va在线播放| 国产电影一区在线| 亚洲手机成人高清视频| 欧美午夜精品久久久| 三级精品在线观看| 久久精子c满五个校花| 97se狠狠狠综合亚洲狠狠| 一区二区三区成人在线视频| 欧美精品777| 国产69精品久久久久毛片| 亚洲精品伦理在线| 9191国产精品| 丁香激情综合国产| 亚洲综合视频在线| 精品久久久久久久一区二区蜜臀| 成人一区二区三区视频| 亚洲图片欧美视频| 久久奇米777| 欧美综合天天夜夜久久| 精一区二区三区| 亚洲黄色av一区| 精品国产91洋老外米糕| 91视频在线观看免费| 久久精品国产在热久久| 1区2区3区国产精品| 日韩午夜激情av| 91免费精品国自产拍在线不卡 | 欧美一卡二卡三卡四卡| 不卡的av在线播放| 精品一区二区三区在线观看国产 | 中文字幕一区av| 日韩精品在线网站| 在线日韩av片| 国产成人免费在线视频| 午夜伦理一区二区| ㊣最新国产の精品bt伙计久久| 精品乱人伦一区二区三区| 色猫猫国产区一区二在线视频| 国产一区在线观看视频| 日韩电影一区二区三区四区| 最新国产精品久久精品| 久久综合久久鬼色中文字| 欧美日韩综合在线| 91同城在线观看| 国产激情偷乱视频一区二区三区| 天天av天天翘天天综合网色鬼国产| 日本一区二区三区国色天香| 欧美成人在线直播| 91精品国模一区二区三区| 日本久久精品电影| 99re亚洲国产精品| av电影在线观看完整版一区二区| 国产一区二区视频在线播放| 日韩在线卡一卡二| 亚洲福利国产精品| 亚洲综合久久久久| 亚洲一区二区在线播放相泽| 亚洲婷婷国产精品电影人久久| 国产日韩影视精品| 国产三级精品视频| 中文av一区特黄| 国产精品免费观看视频| 国产片一区二区| 国产精品免费网站在线观看| 久久久九九九九| 国产欧美日韩综合精品一区二区| 久久影视一区二区| 国产三级精品视频| 国产精品免费免费| 亚洲日本va午夜在线电影| 国产精品久久午夜| 亚洲欧美另类综合偷拍| 亚洲视频中文字幕| 亚洲综合成人网| 日韩av高清在线观看| 另类小说色综合网站| 国产一区二区不卡| 国产99久久精品| 色狠狠一区二区三区香蕉| 欧美色综合网站| 日韩欧美国产系列| 国产清纯白嫩初高生在线观看91| 国产精品私房写真福利视频| 日韩理论在线观看| 亚洲国产美国国产综合一区二区 | 亚洲精品久久7777| 亚洲福利视频一区| 经典一区二区三区| 国产成人精品影视| 欧美在线一区二区| 日韩视频不卡中文| 中文一区二区完整视频在线观看| 亚洲欧洲日韩在线| 日韩电影在线免费观看| 国产精品一区免费在线观看| 99麻豆久久久国产精品免费| 欧美视频一区二区三区四区 | 在线观看91精品国产麻豆| 日韩欧美一二三四区| 中文字幕欧美一| 视频在线在亚洲| 国产99一区视频免费| 欧美狂野另类xxxxoooo| 国产欧美日韩中文久久| 亚洲第一激情av| 成人精品一区二区三区四区| 5月丁香婷婷综合| 国产精品第13页| 青青草成人在线观看| 91丝袜呻吟高潮美腿白嫩在线观看| 欧美撒尿777hd撒尿| 国产精品色婷婷| 日本va欧美va欧美va精品| 99久久精品国产观看| 欧美大片日本大片免费观看| 亚洲日本va午夜在线影院| 经典一区二区三区| 欧美日韩亚洲综合一区二区三区| 日本一区二区三区免费乱视频 | 这里只有精品免费| 中文字幕亚洲欧美在线不卡| 免费人成网站在线观看欧美高清| 91猫先生在线| 中文字幕av一区二区三区免费看 | 欧美综合色免费| 国产精品入口麻豆原神| 日韩av一区二区在线影视| 色婷婷亚洲精品| 欧美高清在线精品一区| 久久国产精品99久久久久久老狼| 欧美日韩在线一区二区| 亚洲免费在线视频一区 二区| 狠狠久久亚洲欧美| 日韩三级中文字幕| 天天综合网 天天综合色| 一本一本大道香蕉久在线精品| 亚洲国产精品t66y| 国产一区二区美女| 26uuu亚洲| 精品中文字幕一区二区| 日韩视频永久免费| 久色婷婷小香蕉久久| 日韩精品一区二区三区视频| 亚洲123区在线观看| 欧美无乱码久久久免费午夜一区 | 美女视频一区二区| 91精品国产综合久久香蕉的特点| 亚洲自拍偷拍综合| 欧美日韩国产首页在线观看| 亚洲图片欧美视频| 9191国产精品| 久久国产精品区|