Виртуаль хүснэгт

__TOC__
## Процедур 
**Stored procedure** гэдэг нь жижигхэн хэмжээний програмыг хэлдэг бөгөөд ганцхан Select командаас эхлээд олон мянган мөр кодтой байж болдог.
Процедурыг ашиглан хүснэгтэд бичлэг нэмэх, устгах, SELECT, UPDATE , Insert into гэх мэт өгөгдлийн санд хийдэг бүх үйлдлийг бичиж болохоос гадна мөн давталтуудыг хийж болно. Курсор ашиглаж хүснэгт бүрийн бичлэг, мөрүүдэд хандах мөн үйлдэл хийх боломжтой болдог.
** Stored procedure ** нь програмчлалын талаас бүтээмж нэмэгдүүлж, T-SQL-ийн командуудын аюулгүй байдлыг хангадаг. Оролт, гаралтын параметрүүдийг хэрэглэх, процедурыг олон дахин хэрэглэх, олон дахин давтагдах үйлдлийг хийх зэрэгт Stored procedure ашигласанаар програмын боломж өснө. Програмчлалын хэлний процедур гэдэг ойлголттой адил.

Stored procedure-ийг үүсгэх
Stored procedure-ийг бусад объектуудаас өмнө үүсгэхийг зөвшөөрнө. Stored procedure-ийг Server Management Studio ашиглан мөн CREATE PROCEDURE, CREATE PROC командаар үүсгэж болно. 

Stored procedure нь дараах боломжуудыг олгодог:
* Групплэгдсэн олон үйлдлийг нэг Stored procedure дотор бичиж үйл ажиллагааг хялбарчилж эмх цэгцтэй болгодог. 
* Оролт, гаралтын параметр, төрөл, авах анхдагч утга тодохойлно. Параметр тодорхойлохдоо нэр нь @ тэмдгээр эхлэх ба дараа нь өгөгдлийн төрөл бичигдэнэ. @ тэмдгээр эхэлсэн бол хувьсагч гэж ойлгож болно. Гаралтын параметрийг оролтынхоос ялгахын тулд OUTPUT түлхүүр үг байх ёстой. 
* Үйлдэл амжилттай биелэгдсэн эсэх талаар мэдэээлэл өгөх 
* Procedure дотор procedure дуудах
* Аюулгүй байдлын үүднээс байгаа Stored procedure-уудыг шифрлэх гэх мэт 
** Процедурыг ашигласнаар ** Өгөгдлийн сангийн боловсруулалтыг маш хурдан болгох боломжтой бөгөөд процедураар дамжуулж параметрүүдийг авч болдог.
** Параметр ашиглах ** Параметр ашиглан програмын үр дүнд гарсан хувьсагчийг дахин ашигладаг. Параметрийн гурван төрөл байдаг.
* in – Процедур луу утга дамжуулдаг. Тухайн процедур дотроо хүчинтэй.
* out – Процедур дотор өөрчлөгдсөн үр дүнг авна.
* inout – Процедурт хадгалагдсан утгаа өөрчилж буцаадаг.

### Ерөнхий бичигдэх хэлбэр: 
```postgresql
DELIMITER $$
CREATE PROCEDURE Procedure_Name()
BEGIN 
       …
	(давталт болон өгөгдлийн санд хийж болдог бүх үйлдлүүдийг хийж болно.)
       …
END $$
DELIMITER;
```

### Процедурыг устгахдаа: 
```postgresql
DROP PROCEDURE Procedure_Name;
```

Процедурыг устгахдаа утга(аргумент) байгаа эсэхийг үл хамаарна.
Анхааруулга: () хаалт бичих шаардлагагүй.

### Процедурыг дуудахад: 
```postgresql
Ямар нэгэн аргумент авдаггүй бол
CALL Procedure_name;
```

```pro_call
Ямар нэгэн аргумент авдаг бол	
CALL 
	Procedure_name(‘argument_name’);
```

### Хувьсагч зарлах: 
```postgresql
Var_name DATATYPE(size);
DEFAULT def_value;
```

### Тайлбар: 
        DATATYPE - төрөл
        size - хэмжээ
        DEFAULT def_value - хувьсагчид утга олгоно

### Хувьсагчид утга олгоход: 
```postgresql
DECLARE Var_name DATATYPE(size);
SET Var_name = value;
```

### Тайлбар: 
	Set – гэсэн түлхүүр үгийн тусламжтай хувьсагчид утга олгох.

### Жишээ: 
```postgresql
DECLARE count int DEFAULT 0;
	SET count = 25;
```

### Дүгнэлт 
Stored procedure-т хувьсагч, функц, буцаах код, анхдагч утга зэрэг програмчлалын элементүүдийг ашиглан бичнэ. Stored procedure-т параметрт дамжуулахгүй мөн параметр буцаахгүй байсан ч болно. Оролтын параметр нь процедурт өгөгдөл дамжуулдаг бол гаралтын параметр  нь процедураас өгөгдөл хүлээн авдаг. Хувьсагчид гаралтын параметрийн утгыг хадгалахад хэрэглэдэг. Хувьсагчийг DECLARE түлхүүр үгээр зарлана. Буцаах утга нь RETURN үгийн тусламжтайгаар тоон хэлбэрээр ирэх ба алдааг заадаг. Алдаа илрүүлэх @@ERROR функц байна. Нэг процедурыг нөгөөгөөс дуудаж болно. Тооны хязгаарлалт байхгүй. Өөрөө өөрийгөө дууддаг процедурыг рекурсив гэнэ.

## Триггер 
** Triggers **-ийн тусламжтайгаар өгөгдлийн бүрэн бүтэн байдлыг хангах нь INSERT, UPDATE, DELETE команд биелэгдсэний үр дүнд гарах хүснэгтэн хэлбэрийн өгөгдөлтэй ажиллах процедуруудыг бичих боломжийг триггерүүд олгодог. Өөрөөр хэлбэл өгөгдөл оруулах, засах, устгах үйлдэл хийгдэх бүрт байнга ажиллах функц гэж ойлгож болно. Нэг триггер хэд хэдэн үйлдэл гүйцэтгэж чаддаг. Temporary/түр зуурын/ болон системийн хүснэгтэнд триггерийг холбож болохгүй. ON DELETE, ON UPDATE хязгаарлалтууд тавигдсан хүснэгтүүд INSTENT OFF DELETE INSTEAD OF UPDATE триггерүүд тодорхойлж болохгүй. Триггерийг гараар ажиллуулж болдоггүй. Програмын өмнө триггерийн синтакс биелэгдэх үйлдэл, төрөл хоёр давхцаж байх ёстой. Триггер хүснэгтэд өгөгдөл хадгалах, шинэчилэхэд шинэ хүснэгт санах ойд INSERTED хүснэгтэд, харин хүснэгтээс өгөгдөл устгахад Deleted  хүснэгтэд  хадгалдаг. T-SQL эдгээр хүснэгтүүдэд хандах боломжтой. Instead of, after гэсэн хоёр төрлийг триггер байдаг. Instead of триггер нь тухайн үйлдэл биелэгдэж эхлэхэд үйлдлийн оронд биелэгдэнэ. Харин after триггер үйлдлийн дараа биелэгддэг. Хүснэгтэд энэ хоёр төрлийн триггерийг давхар холбохыг зөвшөөрдөг. Хэрэв хүснэгтэд хязгаарлалт хийгдсэн байгаа хоёр төрлийн триггер оршин байвал эхлээд instead of триггер , дараа нь хязгаарлалт явагдаж, эцэст нь after триггер ажиллана. Хэрэв хязгаарлалт ямар нэгэн байдлаар зөрчигдөж, эсвэл өөр үйлдэл биелэгдвэл after триггер ажиллахгүйд хүрнэ. Гучин хоёр түвшинт триггер бие биенээ агуулж болох ба триггер рекурсив байдлаар ажиллах боломжтой. Триггертэй ажиллах isql нь триггер болон алдааг үүсгэх, өөрчлөх, устгах боломжтой.
Триггерийг байгуулахдаа CREATE TRIGGER командаар байрлуулах бөгөөд тэр нь толгой (header) болон их бие (body) гэсэн хоёр хэсгээс бүрдэнэ.
** Триггерийн толгой нь дараах зүйл агуулна : **
* Мэдээллийн санд давтагдашгүй триггерийн нэр
* Триггерт холбоотой хүснэгтийн нэр
* Триггер ажиллах үйлдлийн нэр
* Локал хувьсагчуудыг нэр ба тодорхойлолтууд
* BEGIN, END оператораар хязгаарлагдсан командууд. Командууд нь триггерийн хийх үйлдлүүдийг заана. Их бие нь дотроо өөр блок хэрэглэж болох ба блокуудын үеийн тоог маш олон байж болно.
** Чухал ** нь триггер доторх командуудыг цэг таслалаар хязгаарладаг болохоор триггер өөрийг нь хязгаарлах өөр тэмдэгт оруулах шаардлагатай. ** isql** -д үүний тулд CREATE TRIGGER-ын өмнө SET TERM команд хэрэглэж хязгаарлагч тэмдэгтийг өөрчилдөг. Триггерийн их бие дууссаны дараа дахин SET TERM хэрэглэж хязгаарлагчийн хэвийн байдалд (цэг таслал)-д оруулна. 
### Триггерийг байгуулах синтакс 
```postgresql
CREATE TRIGGER name FOR table
[ACTIVE | INACTIVE]
{BEFORE | AFTER}  {DELETE | INSERT | UPDATE}
[POSITION number]
AS

 = 
[]

 =
DECLARE VARIABLE variable datatype;
[DECLARE VARIABLE variable datatype; . . .]

 =
BEGIN

[ . . .]
END

 =
{ | statement;}
```

** Триггерийг байгуулах командын аргумент **

### InterBase-ын процедур ба триггерийн хэл 
InterBase-ын процедур ба триггерийн хэл нь хадгалдаг процедур болон триггер бичихэд зориулагдсан програмчлалын төгс хэл юм. Хэл нь дараах зүйлээс бүрдэнэ:

SQL-ын мэдээллийн боловсруулах командууд : INSERT, UPDATE, DELETE ганцаарчилсан (дан-singleton) SELECT.

SQL-ын оператор болон илэрхийлэл, хэрэглэгчийн тодорхойлсон мэдээллийн сервер болон генераторуудын холбоос.

SQL- хэлний бүхэл бололцоо : утга авх оператор, нөхцөл, шалгуурт операторууд, контекстийн хувьсагчууд, event боловсруулах командууд, алдааны командууд.

Хадгалдаг процедур, триггер хоёр өөр өөр үүрэг зорилготой хэдий ч хоёулаа энэ хэлийг ашигладаг. Харин процедур ба триггерийн хэлийг хэрэглэхдээ дараах хязгаарлалттай: Триггерийн хувьд контекстийн хувьсагчууд (context variables) давтагдашгүй байх ёстой

Хадгалдаг процедурын хувьд хариу эргүүлж өгдөг SUSPEND, EXIT командууд, оролт, гаралтын параметрүүд давтагдашгүй байна.
** Процедур ба триггерийн хэлний өргөтгөлүүд (extension) **

### SET TERM -ыг ** isql ** -д ашиглах 
Триггерийн команд болгон цэг таслалаар хязгаарлагддаг болохоор триггерийг өөрийн хязгаарладаг тэмдэгт хэрэгтэй болно. iql -д үүний тулд CREATE TRIGGER командын өмнө SET TERM гэдэг үгийг хэрэглэж хязгаарлагчийг өөр тэмдэгтээр солино. Триггер дууссаны дараа дахин SET TERM -ыг ашиглан хязгаарлагчийг буцааж цэг таслал болгоно.
SET TERM энэ хоёр үгний хооронд ёул зай байх ёстой. SET TERM -ыг өөрийн хэрэглэж байгаа (current) тэмдэгтээр хязгаарлана.
Триггер дахь синтакс (үг, үсгийн) алдаанууд:
CREATE TRIGGER - командад үг үсгийн алдаа байвал InterBase нь энэ тухай мэдээлнэ. 

** Жишээ **

```postgresql
Statement failed, SQLCODE = -104
Dynamic SQL Error
-SQL error code = - 104
-Token unknow - line 4, char 9
-tmp
```

Мөрний дугаар нь командын файлын эхлэлээс биш гагцхүү CREATE TRIGGER командын эхлэлээс хойших дугаар.

** Триггерийн толгой: **
CREATE TRIGGER командын AS операторын өмнө орсон бүх зүйл нь триггерийн толгой юм. Толгой нь заавал триггерийн нэр, холбогдох хүснэгтийн юм уу харах хүснэгтийн нэртэй байна. Хүснэгт буюу харах хүснэгт нь триггерээс өмнө байгуулагдсан байх ёстой.
Дараахь операторууд нь триггерыг ажиллах нөхцөл, мөчийг тодорхойлно:

Триггерийн статус ACTIVE, INACTIVE триггерийг ажиллах эсэхийг заана. Суурь статус нь ACTIVE - триггер нөхцөл мөч нь бий болсон үед биелэгдэнэ. Туршилтын үед ALTER TRIGGER -аар статусыг INACTIVE болгож болно.

Триггерийн биелэгдэх мөч BEFORE, AFTER нь триггерийг хэзээ ажиллах вэ гэдгийг заана. BEFORE нь үйлдлийн өмнө хийгдэнэ, AFTER нь үйлдлийн дараа.

Триггерийн үйлдэл INSERT, DELETE, UPDATE нь триггер ямар үйлдэл болоход ажиллах вэ гэдгийг заана. Дээрх гурван үйлдлийн аль нэг нь заавал заагдсан байх ёстой. Нэг үйлдэл дээр олон өөр нэртэй триггер байж болно.

Биелэгдэх дэс дарааллын дугаар POSITION number гэдэг нь адил үйлдэл дээр тодорхойлогдсон триггерүүдийн эхэлж ажиллах дарааллыг заана. Дугаар нь 0-оос 32767 хүртэл бүхэл тоо, суурь утга нь тэг, бага дугаартай триггер эхэлж ажиллана, адил дугаартай триггерүүд санамсаргүй дарааллаар ажиллана.
** Доорх жишээнд дарааллын дугаарыг яаж заахыг үзүүлнэ: **

```postgresql
CREATE TRIGGER A FOR ACCOUNTS BEFORE UPDATE POSITION 5 AS . . .
CREATE TRIGGER B FOR ACCOUNTS BEFORE UPDATE POSITION 0 AS . . .
CREATE TRIGGER C FOR ACCOUNTS AFTER  UPDATE POSITION 5 AS . . .
CREATE TRIGGER D FOR ACCOUNTS AFTER  UPDATE POSITION 3 AS . . .
```

** Триггерийн их бие: **
CREATE TRIGGER командын AS операторын хойно орсон бүх зүйлийг триггерийн их бие гэнэ. Их бие нь BEGIN ба END -н хооронд байрласан InterBase-ын процедур ба триггерийн хэлний командуудаас бүрдэнэ.

InterBase-ын процедур ба триггерийн хэлний онцлог командууд нь :

Утга өгөх команд (локал хувьсагчуудад утга өгнө)

Нөхцөлт командууд - IF . . . THEN, WHILE . . . DO, FOR SELECT . . . DO

Хадгалдаг процедур дуудах EXECUTE PROCEDURE команд 

Алдааны мэдээлэл өгдөг, алдаа боловсруулдаг тодорхой алдаа заадаг WHEN команд 

Баганын хуучин ба шинэ утгыг илэрхийлэх NEW ба OLD контекстийн хувьсагч.

Давтагдашгүй утга гаргах генератор.

** Тайлбар **

 Контекстийн хувьсагчаас бусад бүх командуудыг триггер болон процедурын аль алинд нь хэрэглэнэ.

** “Хадгалдаг процедуртай ажиллах”-аас дэлгэрэнгүй харна уу? **

```postgresql
NEW and OLD Context variable
NEW and OLD Context variable
```

Триггер нь контекстийн хоёр хувьсагч ашигладаг NEW ба OLD. 
NEW нь INSERT ба UPDATE командад баганын шинэ утгыг илэрхийлсэн контекстийн хувьсагч, OLD нь UPDATE ба DELETE командад баганын хуучин утгыг илэрхийлсэн контекстийн хувьсагч юм.
* Контекстийн хувьсагчийн синтакс

```postgresql
NEW.column
OLD.column
```

column нь дурын баганын нэр. Контекстийн хувьсагчийг ердийн хувьсагчийн хэрэглэхтэй адил.

Баганын шинэ утгыг зөвхөн үйлдлийн өмнө өөрчилж болно. Хэрвээ триггер INSERT-ын дараа (AFTER) гэж тодорхойлогдсон бол NEW-ийн утгыг өөрчлөх нь ямар нөлөө үзүүлэхгүй. Доорх жишээнд EMPLOYEE хүснэгтийн триггер нь өөрчлөлт орсны дараа шинэ ба хуучин утгуудын жишээ байна. Хэрвээ salary баганад өөрчлөлт орсон бол SALARY_HISTORY хүснэгтэд бичилт нэмнэ.

```postgresql
SET TERM !! ;
CREATE TRIGGER SAVE_SALARY_CHANGE FOR EMPLOYEE
AFTER UPDATE AS
BEGIN
IF (OLD.salary <> NEW.salary) THEN
INSERT INTO SALARY_HISTORY
(EMP_NO,CHANGE_DATE,UPDATER_ID,OLD_
SALARY,PERCENT_CHANGE)
VALUES (OLD.emp_no, “now”, USER, OLD.salary,
 (NEW.salary - OLD.salary) * 100 / OLD.salary);
END !!
SET TERM ; !!
```

** Тайлбар: ** SQL-ын командаас бусад тохиолдолд контекстийн хувьсагчид цэг тэмдэгтийг ашиглахгүй.

** Генераторыг ашиглах: **
Генератор гэдэг нь дуудах бүрт автоматаар нэмэгддэг GEN_ID() функц юм. Генераторыг процедур, триггертэй төстэй application-уудад хэрэглэдэг ба unique баганын утгуудыг гаргадаг триггерт голчлон ашигладаг.  
Генераторыг CREATE GENERATOR ашиглаж үүсгээд SET GENERATOR -аар тохируулдаг. Тохируулга хийгээгүй бол генераторын утга 0-с эхэлнэ.  “Language Reference”-с дэлгэрүүлж үзнэ үү. 
GEN_ID() функцээр генераторыг дуудахаас өмнө CREATE GENERATOR -аар үүсгэсэн байх хэрэгтэй. Синтакс:
	GEN_ID(genname, step)
genname - генераторын нэр
step	- генераторын утгыг нэмэгдүүлэх алхам, бүхэл тоо байж болохоос гадна бүхэл тоо гаргадаг илэрхийлэл байж болно.
Дараах ** жишээнд ** CUSTOMER хүснэгтэд утга нэмэхээс(insert) өмнө шинэ үйлчлүүлэгчийн дугаарыг гаргахад GEN_ID() функцийг ашиглаж байна:

```postgresql
SET TERM !!;
CREATE TRIGGER SET_CUST_NO FOR CUSTOMER
BEFORE INSERT AS
BEGIN
     NEW.cust_no = GEN_ID(CUST_NO_GEN, 1);
END!!
SET TERM ;!!
```

### Триггерийг өөрчлөх 
Триггерийг өөрчлөхдөө ALTER TRIGGER ашиглана. Триггерийг зөвхөн үүсгэсэн хүн өөрчилнө. 
ALTER TRIGGERS ашиглаж зөвхөн дараах зүйлүүдийг өөрчилж болно:
* Зөвхөн толгой (Энд: event, триггерийн дугаар, trigger activation status)
* Зөвхөн их бие (AS -аас хойш орсон)
* Толгой ба их бие . Энэ тохиолдолд хуучин мэдээлэл нь шинэ мэдээллээр солигдоно.
Триггерийн толгойг өөрчлөхдөө ALTER TRIGGER -ийн триггерийн нэрийн дараа ганц өөрчлөлтийг бичнэ. Илүү байгаа өөрчлөлтүүдийг хийхгүй. Эхлээд триггерийг идэвхгүй болгоно: 

```postgresql
ALTER TRIGGER SAVE_SALARY_CHANGE INACTIVE;
```

Триггерийн биеийг өөрчлөхдөө хуучин их бие шинэ тодорхойлолтоор солигдоно. Триггерийн зөвхөн их биеийг өөрчлөх бол ALTER TRIGGER -т триггерийн нэрээс өөр толгойн ганц ч мэдээллийг агуулаагүй байх ёстой. Триггерийн их биеийг өөрчлөхдөө: Мэдээлэл агуулсан файлыг (data definition file) хуулж хадгална. Үүнтэй адилаар ISQL - extract командаар триггерийг мэдээллийн сангаас файл руу задална.
CREATE -г ALTER болгож триггерийн нэр ба AS -н хооронд орших толгойн мэдээллийг арилгана.

Дараах ** жишээнд ** SET_CUST_NO триггерийн их биеийг өөрчилж, шинэ үйлчлүүлэгч бүрийн мэдээллийг NEW_CUSTOMER хүснэгтэд нэмдэг болгож байна.

```postgresql
SET TERM !!;
ALTER TRIGGER SET_CUST_NO
BEFORE INSERT AS
BEGIN
      new.cust_no = GEN_ID(CUST_NO_GEN, 1)
      INSERT INTO NEWCUSTOMER(new.cust_no, TODAY)
END!!
SET TERM ;!!
```

** Триггерийг устгах: ** триггерийг бүрмөсөн (permanently) устгахдаа DROP TRIGGERS ашиглана.
Триггерийг устгахад дараах хязгаарлалтууд байдаг: Триггерийг үүсгэсэн хүн л устгаж болно.
Хэрэглэгдэж байгаа триггерийг устгаж чадахгүй.
Триггерийг түр зуур арилгах (temporarily remove) шаардлагатай бол ALTER TRIGGER -ийн INACTIVE -г ашиглах хэрэгтэй.
** Триггерийг устгах синтакс **

```postgresql
DROP TRIGGER name;
```

name нь оршин байгаа триггерийн нэр. ** Жишээ: **

```postgresql
DROP TRIGGER SET_CUST_NO;
```

** Санамж: ** CHECK дотор хэрэглэгдэж байгаа триггерийг (a system-defined trigger) устгаж чадахгүй. ALTER TABLE ашиглаж CHECK -г өөрчил.

### Триггерийг ашиглах 
Триггер нь янз бүрийн зорилгоор ашиглаж болох хүчтэй хэрэгсэл юм. Триггерийг ашиглах янз бүрийн тохиолдлууд байна:
Хамааралтай өөрчлөлтүүд хийх. (Correlated updates). Жишээ нь мэдээллийн сан буюу хүснэгтийн өөрчлөлтийн log файл үүсгэх
Хүснэгтэд зөвхөн зөв өгөгдлийг оруулах хязгаарлалт хийх. 
Event ашиглаж мэдээллийн сангийн өөрчлөлтийн талаар мэдээлэх
Шат дараалсан өөрчлөлтүүдийг хийх (cascading referencial integrity updates)
Триггер нь хадгалагдсан процедур, exception -уудын адилаар мэдээллийн сангийн нэг хэсэг болон хадгалагдана.ACTIVE байдалд байгаа бол устгах(DROP TRIGGER), идэвхгүй болгох(ALTER TRIGGER INACTIVE) хүртэл идэвхтэй байсаар байна. 
Триггерийг шууд дууддаггүй. Тухайн хүснэгтэд тухайн үйлдэл (action) болох үед триггер автоматаар ажиллана.
* Анхаар: Тухайн нэг триггер нь өөрийгөө ажиллуулах үйлдэл хийдэг- эсвэл өөрийг нь ажиллуулдаг өөр триггерийг ажиллуулах үйлдэл хийдэг бол төгсгөлгүй үргэлжилсэн үр дүн гарна. Ийм учраас шаардлагагүй бол триггерийн үйлдэл нь өөр триггерийг ажиллуулах нөхцөл болохгүй байх нь чухал юм.
** Триггер ба транзакци ** триггер нь үйлдэл хийх үедээ программын транзакцийн контексттэй ажилладаг. Триггер нь дуудаж буй программын (calling program) ажлын нэг хэсэг нь болно. Хэрэв триггер нь транзакцид ажилладаг бол транзакц дууссаны дараа триггерийн үйлдэл мөн дуусна.
** Триггер ба нууцлал ** Триггер нь процедур ба хэрэглэгчийн нэгэн адилаар хүснэгтийг ашиглах эрхтэй байна. Гэхдээ GRANT TO username гэж бичихийн  оронд TO TRIGGER trigger_name гэж бичнэ. REVOKE мөн адил. Хэрэглэгч триггерийг ажиллуулах үйлдэл хийхэд:
* триггер тухайн үйлдлийг хийх эрхтэй бол
* хэрэглэгч тухайн үйлдлийг хийх эрхтэй бол гэсэн тохиолдлуудад триггер үйлдлийг хийх эрхтэй байна.
** Жишээ нь: ** Хэрэв нэг хэрэглэгч A хүснэгт дээр UPDATE хийдэг ба В хүснэгтэд INSERT хийдэг триггерийн ажиллах нөхцөл болдог бол хэрэглэгч INSERT хийх эрхтэй тохиолдолд л триггер нь INSERT хийх эрхтэй болно.
Триггер тухайн үйлдлийг хийх эрхгүй бол Interbase SQLCODE алдааны дугаарыг буцаана. Триггер нь WHEN командын тусламжтайгаар алдааг боловсруулж болно. Хэрэв алдааг боловсруулдаггүй бол application -д алдааны мэдээлэл очих ба триггерийн үйлдэл хийгдэхгүй.
** Триггерээр event үүсгэх ** триггер нь мэдээллийн санд өөрчлөлт хийгдсэн үед event үүсгэж болно. ** Жишээ нь: **

```postgresql
SET TERM !!;
CREATE TRIGGER POST_NEW_ORDER FOR SALES
AFTER INSERT AS
BEGIN
     POST_EVENT ”new_order”;
END!!
SET TERM;!!
Триггер event-ийн нэрэнд хувьсагч хэрэглэж болно:
POST_EVENT :event_name;
```

### Алдааны мэдээлэл 
Exception  гэдэг нь хадгалагдсан процедур, триггерээс гарах алдааны мэдээлэл юм. Exception-г CREATE EXCEPTION-аар үүсгэж,  ALTER EXCEPTION-аар өөрчилж, DROP EXCEPTION-аар устгана.
* Хүснэгтэд өөрчлөлт хийхэд хэрэв шинэ цалин нь хуучнаас 50-аас дээш хувиар нэмэгдсэн тохиолдолд гардаг алдааны мэдээлэл байж болох юм. ** Жишээ нь: **

```postgresql
New salary exceeds old by more than 50%. Cannot update record.
```

* ** Чухал: ** нь процедур, триггерийн адилаар exception нь мэдээллийн санд үүс ч, хадгалагдах ба мэдээллийн сангийн аль ч процедур, триггерт ашиглагдаж болно. Exception-г триггерт ашиглахаас өмнө мэдээллийн санд үүс ч, хадгалагдсан байх ёстой.
** Триггер дотор алдааг боловсруулах ** триггер дотор алдаа, алдааны мэдээллийг WHEN командаар боловсруулж болно. Алдааны мэдээллийг WHEN командаар боловсруулдаг бол application-д мэдээлэл буцахгүй ба триггерийн үйл ажиллагааг заавал таслах албагүй юм.
Триггерийн алдааны боловсруулалт (error handling) нь хадгалагдсан процедуртай адилхан ажиллана: WHEN хүртэл хийгдсэн үйлдлүүд нь буцах (undone) бөгөөд WHEN команд ажиллана.
** триггер дотор алдааны мэдээлэл гаргахдаа дараах синтакстай бичнэ: **

```postgresql
EXCEPTION name;
```

name - мэдээллийн сан дээр оршин байгаа алдааны мэдээлэл. Алдааны мэдээлэл гаргахад:
Триггерийн үйлдлийг буцааж, ажиллагааг зогсооно.
Триггерийг ажиллуулж буй application-д алдааны мэдээллийг буцаана. Хэрэв ISQL командаар триггерийг ажиллуулсан бол дэлгэцэн дээр алдааны мэдээлэл гарна.
* ** Чухал: ** WHEN командаар алдааг боловсруулдаг бол дээрхээс арай ялгаатай байна.
### MSSQL датабаазын хүснэгт дээр триггер бичих 
* ** Insert Trigger **

```postgresql
CREATE TRIGGER trigger_insert1
ON table1
FOR INSERT
AS
BEGIN
UPDATE table2
    SET field_total = field_total + inserted.field_name1
END
```

* ** Update Trigger **

```postgresql
CREATE TRIGGER trigger_update1
ON table1
INSTEAD OF UPDATE
AS
BEGIN
SELECT t1.*, i.* FROM table1 t1
    JOIN inserted i ON t1.field_id = i.field_id
END
```

* ** Delete Trigger **

```postgresql
CREATE TRIGGER trigger_delete1
ON table1
FOR DELETE
AS
BEGIN
INSERT INTO logTableName
    SELECT * FROM deleted
END
```

* ** Trigger Event **
deleted - DELETE trigger үед дата нь deleted гэсэн хүснэгт хэлбэрээр байна.

inserted - INSERT, UPDATE trigger үед дата нь inserted гэсэн хүснэгт хэлбэрээр байна.
* ** Trigger Time **
FOR DELETE – Устгахаас өмнө

FOR INSERT – Нэмэхээс өмнө

FOR UPDATE – Засахаас өмнө

FOR INSERT, UPDATE – Нэмж, Засахаас өмнө

AFTER DELETE – Устгасны дараа

AFTER INSERT – Нэмсний дараа

AFTER UPDATE – Зассаны дараа

AFTER INSERT, UPDATE – Нэмж, Зассаны дараа

INSTEAD OF DELETE – Устгахын оронд

INSTEAD OF INSERT – Нэмэхийн оронд

INSTEAD OF UPDATE – Засахын оронд

INSTEAD OF INSERT, UPDATE – Нэмж, Засахын оронд

## Виртуаль хүснэгт 
** View ** нь хүснэгтэд фильтрийн үүргийг гүйцэтгэдэг. View-ээр хэд хэдэн хүснэгтэд, мөн тухайн болон өөр өгөгдлийн санд зэрэг хандах өгөгдөл авч чаддагаараа онцлог. Мөн ижил бүтэцтэй ч өөр серверүүд дээрх мэдээллийг нэгтгэхэд тустай. View-г виртуаль хүснэгт эсвэл хадгалагдсан тайлан гэж нэрлэж болно. Стандарт View-н хувьд өгөгдлийн сан тухайн view биш, харин түүнийг тодорхойлогч SELECT команд байдаг. SELECT командын үр дүнд гарсан виртуаль хүснэгтийг View буцаадаг. 

Дараах хэдэн үүргийг гүйцэтгэдэг:
* Хэрэгтэй мөр, баганыг харах боломжийг хэрэглэгчид олгодог. 
* Тусдаа хүснэгтүүдээс багануудыг нэгтгэж нэг хүснэгт хэлбэрээр харах. 
* View болон table-ээс дахин view үүсгэх.
* Багануудын хооронд үйлдэл оруулж харах. 
* Өгөгдлийг хүссэн байдлаар хялбар аргаар харах. 

View-н тусламжтайгаар хэрэглэгчид хэрэгтэй байгаа мөр баганыг харуулах ба хэрэглэгч хүснэгтийг өөрийг нь биш view-г  харсанаар өгөгдлийн найдвартай байдлыг өсгөдөг. Нэг view-г дараа өөр view-д хэрэглэж болно. Олон янзын сонирхолтой өөр өгөгдөл хэрэглэгчид өөр байдлаар мэдээлэл харуулах боломж олгодогоороо давуу талтай. Microsoft Excel зэрэг өөр програмууд руу мэдээлэл хөрвүүлж гаргах боломжтой. 

** VIEW үүсгэх: ** 
View-г ямар ч өгөгдлийн санд үүсгэж болдог. Тухайн хэрэглэгчийн бусад объектуудтай нэр давхцаж болохгүй. Нэг view-с дахин өөр өөр view үүсгэж болох боловч шаталсан гучин хоёр түвшинг зөвшөөрнө. View үүсгэхэд дараах хязгаарлалтууд байна: 

* View-тэй rules, default-г холбож болохгүй. 
* View-д instead of триггерийг холбохыг зөвшөөрнө. Харин after триггерийг холбож болохгүй. 
* View тодорхойлох кодонд compute, compute by, into түлхүүр үг байж болохгүй. 
* Temporary /түр зуурын хүснэгт/-ээс view үүсгэх мөн temporary /түр зуурын/ view үүсгэх боломжгүй. 
* Schema binding-г ашиглан гаргасан view-с үүсгэхэсэн хүснэгт view-г устгаж болохгүй. Хэрэв view-н баганын нэр арифметик үйлдэл, функц, тогтмол агуулсан байвалхэд хэдэн багана ижил нэртэй байх аюул тулгарах тул view-н нэрийг хэрэглэгч тодорхой заах хэрэгтэй. View-н баганын төрөл нь суурь хүснэгтийн тухайн баганын төрлийг хэвээр хадгална. View-г үүсгэхдээ заавал тухайн өгөгдлийн санг өөрчлөх эрхтэй байхыг шаардана. 
 
** Индекслэгдсэн view-г үүсгэх: **
Индекслэгдсэн view-г Microsoft SQL Server 2008 enterprise, Microsoft  SQL server developer edition дээр л үүсгэж болно. View-д үүсгэх эхний индекс цорын ганц ба кластерын индекс байх ёстой. Үүний дараа нэмэлт индексийг үүсгэж болно. CREATE INDEX командаар үүсгэхдээ индэксийн нэрийн оронд view-н нэрийг тавих ёстой мөн CREATE INDEX командаар дараах хязгаарлалтууд байна. 

* CREATE INDEX командыг ажиллуулж буй хэрэглэгч view-н хэрэглэгч байх ёстой. 
* NUMERIC_ROUNDABORT параметрт off хийх ёстой. 
* View-д  text, ntext, image төрлийн багана байх ёсгүй. 
* CREATE INDEX командыг хэрэглэх үед дараах параметрүүдийг on хийх ёстой. Үүнд:  ANSI_NULLS, ANSI_PADDING, ANSI_WARNING, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUATED_IDENFEIRS Индекслэгдсэн view-д дараах шаардлагууд тавигддаг. 
* CREATE VIEW командыг гүйцэтгэх үед ANSI_NULLS, QUITED_IDENTFERS  параметрүүд on байх хэрэгтэй. 
Эдгээр параметрүүдийг утгыг OBJECTPROPERTY функцын ExecIsAnsiNullsOn, EXECLSOUCTEDDENTOn–р мэдэж болно. CREATE TABLE-н бүх команд ажиллаж эхлэхэд ansiNulls параметр null байх ёстой. Бүх суурь хүснэгтээс бусад хүснэгт рүү холбогдож болохгүй. Суурь хүснэгтүүд тухайн өгөгдлийн санд байх ёстой. View үүсгэхдээ view-г суурь хүснэгтийн схемтэй холбож байдаг. SCHEMABINDING параметртэй байх ёстой. Хэрэглэгчийн функц мөн SCHEMABINDING параметртэй байх ёстой. Хэрэв GROUP BY заагдсан бол COUNT_BIG(*) байх ёстой ба харин HAVING, CUBE, ROLLUP байхыг зөвшөөрөхгүй. Бодолт хийх үед баганы утга хөвөгч таслалтай байх зайлшгүй шаардлагатай бол тийм баганыг индекслэгдсэн view(эсвэл хүснэгт)-ийн түлхүүр индексээр авахыг зөьшөөрдөггүй. Үүнээс гадна T-SQL хэлэнд индекслэгдсэн view-ийн синтакст дараах элементүүдийг агуулж болохгүй. Үүнд 

* Од (*) 
* View-ийн нэгээс илүү багананд заагдсан хүснэгтийн баганы нэр
* Анхдагч бус хүснэгт
* Мөрүүдтэй ажиллагдаг функцууд, UNION команд
* Дэд тайлан
* Гадаад холболт, өөрөө өөртэйгээ холбогдох
* TOP, ORDER BY, COMPUTE, COMPUTE BY, CONTAINS, FREETEXT, DISTINCT түлхүүр үг
* COUNT(*), (COUNT_BIG()зөвшөөрөгддөг)
* AVG, MAX, MIN, STDEV, STDEVP, VAR, VARP функцууд, Үр дүн нь хоосон утга авах SUM функц. 

** Секцлэгдсэн view үүсгэх: **
Microsoft Server 2008-д дотоод ба гадаад гэсэн хоёр секцлэгдсэн view байдаг. Дотоод секцлэгдсэн view гэдэг нь бүх суурь хүснэгтүүд нэгэн SQL Sever дээр байрладаг бол гадаад секцлэгдсэн view-д дор хаяж нэг хүснэгт нь өөр сервер дээр байрладаг. Гадаад секцдэгдсэн view нь өгөгдлийн сангийн серверүүдийг нэгтгэхэд тустай. Энд нэгтгэх гэдэг нь өгөгдлийн сангийн боловсруулалтыг тус тусдаа боловч хамтран гүйцэтгэхийг хэлж байна. Олон тооны сервертэй томоохон хэмжээний өгөгдлийн санд нэгтгэх процесс хэрэгтэй байдаг. View нь оролцогч-хүснэгтүүдийн тоотой тэнцүү тоотой жижиг хүснэгтүүдэд хуваагддаг. Оролцогч-хүснэгтүүдийн баганы тоо анхдагч хүснэгтийн баганы тоотой тэнцүү байна.  Мөн оролцогч-хүснэгтүүдийн нэр оролцогч-сервер дээр ижил байдаг ч заавал тийм байх ёстой биш. Оролцогч-хүснэгтүүдийг үүсгэсэний дараа сервер бүр дээр гадаад секцлэгдсэн view-г ижил нэртэйгээр тодорхойлох хэрэгтэй. Энд нь дурын сервер дээр байгаа секцлэгдсэн view-тэй холбогдож, тухайн сервер дээр анхдагч хүснэгтийн хуулбар буй мэтээр ажилладаг. Гадаад секцлэгдсэн view дараах дараалалаар үүсдэг.
Оролцогч-сервер бүр дээр серверүүдийн холбоос тодорхойлогдоно. Үүний үр дүнд гадаад секцлэгдсэн view холбоотой бусад серверүүд дээрх мэдээлэлд хандах эрх олж авна.
Sp_serveroption  процедураар схемийг шалгана. Ингэсэнээр алслагдсан серверт байгаа санг хэрэглэхгүй ч view үүсгэх явцад гадаад өгөгдөл бэлэн байхыг шаардсан анхааруулга гаргахгүй байлгадаг. 
Оролцогч-сервер бүр дээр гадаад секцлэгдсэн view үүснэ. SELECT командаар холбоотой оролцогч-серверүүдийн өгөгдөл хандах, мөн дотоод, гадаад оролцогч-хүснэгтүүдийн мөр устгахад хэрэглэдэг.

** View устгах: **

Цаашид хэрэглэхээ больсон view, view-д хандах эрх болон үзүүлэлт өөрчлөхөд view-г устгадаг. DROP VIEW командаар view-г устгадаг. View-н тусламжтай өгөгдөлд хандаж болно.Мөн view-ийн буцаах өгөгдлийн төрлийг илүү нарийн заах боломжтой.

View гэдэг бол SQL тайлангийн үр дүнгийн олонлог дээр суурилсан виртуал хүснэгт юм. View нь бодит хүснэгт шиг мөр ба баганын өгөгдлүүдээс бүрдэнэ. Хүснэгтэд өгөгдөл хадгалж байхад view шаардлагууд хадгалж өгөгдлүүдийг хэрэгцээтэй үед татаж байдагт эдгээрийн гол ялгаа оршино. View нь өгөгдлийн санд нэг буюу хэд хэдэн бодит хүснэгтүүдээс бүрддэг. SQL VIEW үүсгэж, өөрчилж, устгаж болдог. Үүний бичиглэл болон жишээнүүдийг харна уу.
### Виртуаль хүснэгт үүсгэх бичиглэл: 
```postgresql
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;
```

* ** Тайлбар: ** View үргэлж сүүлийн үеийн мэдээллийг харуулж байна. Өөрөөр хэлбэл өөрчлөгдөж(update) байна гэсэн үг юм.
** Виртуаль хүснэгт үүсгэх жишээ **

```postgresql
CREATE VIEW [Current Product List] AS
SELECT ProductID, ProductName
FROM Products
WHERE Discontinued = No;
```

** Дараах байдлаар кверигээ шалгаж болно **

```postgresql
SELECT * FROM [Current Product List];
```

### Виртуаль хүснэгтийг өөрчлөх бичиглэл: 
```postgresql
CREATE OR REPLACE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;
```

** Виртуаль хүснэгтийг өөрчлөх жишээ: **

```postgresql
CREATE OR REPLACE VIEW [Current Product List] AS
SELECT ProductID, ProductName, Category
FROM Products
WHERE Discontinued = No;
```

** Виртуаль хүснэгтийг устгах бичиглэл: **

```postgresql
DROP VIEW view_name;
```

** Дүгнэлт **
 
View бол өгөгдлийн хялбар, ойлгомжтой, хэрэглэгчид хэрэгтэй хэлбэрээр харуулах өргөн хэрэглэгддэг объект юм. Стандарт view-ээс гадна индекслэгдсэн view байдаг. View-г үүсгэж,  нэр өөрчилж, устгаж болно. View устгахад суурь хүснэгтийн өгөгдөлд нөлөөлөхгүй. Мөн view-ээр дамжуулж өгөгдөлд хандах боломжтой.

## Ашигласан материал 
1. https://docs.microsoft.com/en-us/sql/t-sql/statements/create-procedure-transact-sql

2. https://web.archive.org/web/20150511165028/http://www.mssqltips.com/sqlservertutorial/161/creating-a-simple-stored-procedure

3. https://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html

4. https://www.w3schools.com/sql/sql_view.asp
## Мэдээлэл оруулсан 
B140920089