تبلیغات

جبررابطه ای

جبر رابطه ای یک زبان پرس و جو است که عملیات روی پایگاه داده را توسط نمادهایی به صورت فرمولی بیان می کند.

Selection
Projection
Cartesian Product
Set Union
Set Difference
Cartesian Product
Set Intersection
Division
Join
مثال کاربردی


جبر رابطه ای (relational algebra) عملیات روی پایگاه داده را به صورت فرمول بیان می کند. جبر رابطه ای توسط Codd به عنوان مبنای زبان های پرس و جوی پایگاه داده ارائه شد. عملگرهای جبر رابطه ای توسط نمادهائی نمایش داده می شوند.

شش عملگر مبنائی جبر رابطه ای که توسط Codd تعریف شد عبارتند از:

• Selection: σ
• Projection:
• Cartesian Product: ×
• Set union:
• Set difference: –
• Rename:

اکثر عملگرهای دیگر توسط این عملگرها تعریف می شوند. مهمترین آنها عبارتند از:

• Set Intersection:
• Division: ÷
• Natural Join:

هر عملگرجبر رابطه ای روی یک یا دو رابطه به عنوان ورودی عمل کرده و یک رابطه جدید را به عنوان نتیجه تولید می کنند.


Selection

عملگر انتخاب (selection) یک عملگر یکتائی است که سطرهائی از یک رابطه را انتخاب می کند. فرم کلی آن به صورت زیر است:

σشرط(R)

خروجی عملگر selection رابطه ای است شامل سطرهایی از رابطه R که شرط موردنظر در آنها برقرار بوده است.

کاردینالیتی جدول حاصل کمتر یا مساوی جدول اولیه است اما درجه آنها تفاوت نمی کند.

شرط می تواند توسط علائم = ، ،> ،< ، ، ، (and) ، (or) و ~(not) ساخته شود.


Projection

عملگر پروژه (projection) عملگر یکتائی که ستون هائی از یک رابطه را انتخاب می کند. شکل کلی آن به صورت زیر است:

a1,…,an(R)

a1,…,an مجموعه از اسامی صفات خاصه است که از رابطه R انتخاب می شوند. نتیجه عمل پروژه جدولی شامل کلیه تاپل های رابطه R است که محدود به مجموعه صفات مشخص شده است.

اگر در جدول حاصل سطرهایی مشابه هم باشند با هم ترکیب می شوند و سطرهای تکراری حذف می شوند. معمولا یک کلید کاندید را نگه می داریم تا کاردینالیتی حفظ شود. درجه جدول حاصل کمتر یا مساوی جدول اولیه است.


Cartesian Product

ضرب دکارتی (Cartesian Product) عملگری است که روی دو جدول کار می کند و جدول جدیدی را می دهد که که یک رکورد برای هر جفت رکورد ممکن از هر دو جدول دارد. فرم کلی آن به صورت زیر است:

R × S

رکوردهای های رابطه R با کلیه رکوردها رابطه S به این صورت ترکیب می شوند که اولین سطر از رابطه R در کنار اولین سطر رابطه S در جدول حاصل قرار می گیرد و به همین ترتیب تا آخرین سطر S اضافه می شود. همین عمل مجددا برای سطرهای دیگر رابطه R تکرار می شود.

Cartesian product Example

در جدول حاصل احتمال تکرار شدن ستون ها وجود دارد.

درجه جدول حاصل برابر مجموع درجات دو جدول و کاردینالیتی آن برابر حاصل ضرب کاردینالیتی دو رابطه می باشد.

ضرب دکارتی در جبر رابطه ای متفاوت از آنچه درتئوری مجموعه است تعریف می شود.


Set Union

عملگر اجتماع (union) یک عملگر دوتائی است که مشابه عمل اجتماع در تئوری مجموعه ها عمل می کند. فرم کلی آن به صورت زیر است:

R S

اجتماع دو رابطه R و S جدولی است شامل کلیه تاپل های رابطه R و رابطه S.

دو رابطه ای که روی آنها عمل اجتماع انجام می شود باید همساز(compatible) باشند، یعنی باید دارای مجموعه صفات خاصه یکسان باشند.

Union Example

درجه جدول حاصل تفاوتی نمی کند اما کاردینالیتی آن برابر با مجموع سطرهای هردو جدول منهای سطرهای مشترک است.


Difference

عملگر تفاضل (difference) یک عملگر دو تائی است و مشابه عمل تفاضل در تئوری مجموعه ها است. فرم کلی آن به صورت زیر است:

R - S

تفاضل R و S جدولی است که شامل کلیه تاپل هایی است که در R هست ولی در S نیست. سطر اول رابطه R با کلیه سطرهای رابطه S مقایسه می شود هر کدام که در رابطه S نبود در جدول حاصل قرار می گیرد.

دو رابطه ای که روی آنها عمل تفاضل انجام می شود باید همساز باشند.

Difference Example

کاردینالیتی جدول حاصل برابر کاردینالیتی رابطه R منهای سطرهای مشابه است. درجه آنها تفاوتی نمی کند.


Rename

عملگر تغییر نام (rename) یک عملگر یکتائی است که برای تغییر نام صفات خاصه یک رابطه یا نام خود رابطه استفاده می شود. تغییر نام به صورت نوشته می شود:

A(B)

نتیجه عمل تغییر نام روی رابطه B همان رابطه B است با نام جدید A به بیان دیگر رابطه B را به A تغییر نام می دهد.


Intersection

عملگر اشتراک (intersection) بر اساس عمل اشتراک مجموعه ها می باشد. فرم کلی آن به صورت زیر است:

R S

جدول حاصل از اشتراک دو رابطه R و S جدولی است شامل کلیه تاپل هایی که در هر دو جدول وجود دارد.

دو رابطه ای که روی آنها عمل اشتراک انجام می شود باید همساز باشند.

Intersection Example

Division

عملگر تقسیم (division) روی دو رابطه انجام می شود. فرم کلی آن به صورت زیر است:

R ÷ S

حاصل تقسیم رابطه R بر رابطه S رابطه ای است شامل کلیه تاپل هائی از R برای صفات خاصه مشترک در رابطه S نیز وجود دارد. در جدول حاصل صفات خاصه ای از R اضافه می شود که در S نیست.

Division Example

عمل تقسیم توسط عملگر های مبنائی به صورت زیر شبیه سازی می شود:

T := a1,...,an(R) × S
U := T - R
V := a1,...,an(U)
W := a1,...,an(R) – V


Join

الحاق طبیعی (Natural Join) یک عملگر دوتائی است که به صورت زیر نوشته می شود:

R S

نتیجه الحاق طبیعی رابطه ای است شامل کلیه ترکیبات تاپل های R و S است که صفات خاصه مشترک آنها برابر است.

الحاق دو رابطه زیر مجموعه ای از ضرب دکارتی است. نتیجه ضرب دکارتی بدون هیچ شرطی است و ممکن است اطلاع جدیدی را ندهد. ولی عملگر الحاق با استفاده از کلید خارجی دو رابطه را با هم ترکیب کرده و با حذف سطرهائی از ضرب دکارتی اطلاع معنی داری را از ترکیب جداول می دهد.

دو رابطه که در الحاق شرکت می کنند باید دارای صفت خاصه مشترکی باشند.

مثال. جدول Loan و Borrower که به ترتیب حاوی مشخصات وام ها و وام گیرنده ها هستند را درنبظر بگیرید.

Natural join Example

مثال. در جدول Borrower کلید خارجی فیلد Loan_no است. الحاق جداول Loan و Borrower اسامی وام گیرنده ها و مقدار وام آنها را می دهد.

وقتی عمل الحاق روی دو رابطه انجام می شود بعضی داده ها از دست می روند. بعضی وقت ها این داده ها اطلاعات مفیدی را دارند. الحاق خارجی (outer join) جداول را به نحوی ترکیب می کند که داده های مورد نظر در جدول نتیجه باقی بمانند.

بسته به اطلاعاتی که حفظ می شود سه نوع الحاق خارجی وجود دارد:

left outer join •
right outer join •
full outer join •

left outer join

نتیجه الحاق چپ مجموعه کلیه تاپل های رابطه R و S است که صفات خاصه مشترک آنها یکسان است بعلاوه تاپل هایی در R که برای صفت خاصه مشترک همنظیری در S ندارد. برای این تاپل ها در صفات خاصه ای که از S اضافه می شوند مقدار null قرارداده می شود.

الحاق چپ به صورت زیر نوشته می شود:

R S

مثال. الحاق خارجی چپ دو جدول Loan و Borrower به صورت زیر می شود:

Left outer join Example

الحاق چپ با استفاده ازالحاق طبیعی و اجتماع بدست می آید:

R S = S (R S)

right outer join

الحاق راست مشابه الحاق چپ است با این تفاوت که کلیه مقادیر رابطه سمت راست عملگر الحاق در نتیجه ظاهر می شود.

R S

مثال. الحاق خارجی راست دو جدول Loan و Borrower به صورت زیر می شود:

Right outer join Example

الحاق چپ با استفاده ازالحاق طبیعی و اجتماع بدست می آید:

R S = R (R S)

full outer join

الحاق خارجی کامل یا به طور خلاصه الحاق خارجی الحاق خارجی چپ و راست را با هم ترکیب می کند. نتیجه الحاق کامل خارجی مجموعه کلیه ترکیبات تاپل های R و S است که صفات خاصه مشترک آنها برابر است بعلاوه تاپل هائی در S که در R نیستند و تاپلهای R که در S وجود ندارند.

الحاق خارجی دو رابطه R و S به صورت زیر نوشته می شود:

R S

مثال. الحاق خارجی دو جدول Loan و Borrower به صورت زیر می شود:

Full outer join Example

الحاق خارجی کامل با اجتماع الحاق چپ و الحاق راست بدست می آید:

R S = (R S)(R S)
R S = R S (R S)


مثال های کاربردی

مثال بانک. رابطه های زیر را درنظر بگیرید:

branch (branch_name, branch_city, assets)
customer (customer_name, customer_street, customer_city)
account (account_number, branch_name, balance)
loan (loan_number, branch_name, amount)
depositor (customer_name, account_number)
borrower (customer_name, loan_number)

سوال1. کلیه شماره وام هائی که مقدارشان از 1200 بیشتر است را پیدا کنید.

loan_numberamount > 1200 (loan))

سوال2. کلیه مشتریانی که یک وام، یک حساب یا هردو را پیدا کنید.

customer_name (borrower) customer_name (depositor)

سوال3. کلیه مشتریانی که یک وام و یک حساب در بانک دارند را پیدا کنید..

customer_name (borrower) customer_name (depositor)

سوال4. اسامی کلیه مشتریانی که یک وام در شعبه Perryridge دارند را پیدا کنید..

customer_namebranch_name="Perryridge"(borrower loan))

سوال5. اسامی کلیه مشتریانی که یا حساب دارند یا وام گرفته اند (ولی نه هردو) را پیدا کنید.

customer_name ((σ account_number is null or loan_number is null ( depositor borrower))

سوال6. اسامی کلیه مشتریانی که یک وام در شعبه Perryridge دارند ولی هیچ حسابی در هیچ شعبه ندارند را پیدا کنید..

customer_namebranch_name="Perryridge" (borrowerloan)) – customer_name(depositor)

SQL

SQL یک زبان ساختیافته برای بازیابی و بهنگام سازی داده از یک پایگاه داده رابطه ای است. دستوراتی برای ایجاد، حذف و تغییر اشیای مختلف در پایگاه داده دارد. پرکاربردترین دستور آن برای اجرای پرس و جوهای مختلف روی پایگاه داده استفاده می شود.

CREATE TABLE
DROP TABLE
SELECT
JOIN
DELETE
INSERT
UPDATE
ایرادهای SQL


(Structured Query Language) SQL یک زبان برنامه نویسی تعاملی استاندارد برای بازیابی و بهنگام سازی پایگاه داده رابطه ای است.

SQL اجازه می دهد ایجاد جدول، اضافه و حذف داده، اصلاح داده و اجرای پرس و جوی روی داده به شکل یک زبان فرمانی در آیند.

اولین نسخه SQL در دهه 1970 در IBM توسط Donald D. Chamberlin و Raymond F. Boyce پیاده شد. این نسخه که ابتدا (Structured English Query Language) SEQUEL نامیده شد برای کارکردن و بازیابی داده ذخیره شده درپایگاه داده رابطه ای System R بود.

SQL به عنوان یک استاندارد توسط ANSI در سال 1986 و توسط ISO در سال 1987 پذیرفته شد.

ANSI بیان کرد که تلفظ رسمی آن es queue el است. در حالیکه افراد حرفه ای انگلیسی زبان پایگاه داده هنوز نام آنرا sequel تلفظ می کنند.

گونه هائی از SQL، به عنوان یک زبان پرس وجو و کار با داده، توسط عرضه کنندگان DBMS همراه با ضمایمی ایجاد شد. با بیرون آمدن استاندارد SQL:1999 بسیاری از ضمیمه ها به عنوان بخشی از زبان SQL پذیرفته شدند.

در این بخش فرامینی از SQL که در اکثر گونه ها وجود دارد شرح داده خواهد شد.

فضاهای خالی در عبارات SQL ندیده گرفته می شوند و برای خوانائی کدهای SQL استفاده می شوند. سمیکولن (;) به عنوان پایان دهنده عبارت است.

CREATE TABLE

عبارت Create یک فرمان DDL در SQL است که برای ایجاد یک شیء در پایگاه داده استفاده می شود. احتمالا معمول ترین فرمان Create فرمان CREATE TABLE است.

CREATE TABLE اجازه ایجاد شمای یک جدول را می دهد. فرم کلی آن به صورت زیر است:

CREATE TABLE tablename (
colname  datatype  coloptions
,colname  datatype  coloptions
,colname  datatype  coloptions
,additionalinfo
);

هر سطر یک فیلد جدول را مشخص می کند. تعریف هر فیلد شامل نام، نوع داده و اطلاعات اضافی مربوطه می تواند باشد. سطرها با کاما (,) از هم جدا می شوند.

نوع های داده مختلفی در یک DBMS وجود دارد که مهمترین آنها عبارتند از:

CHAR(n) . رشته کاراکتری ASCII با طول ثابت n کاراکتر
VARCHAR(n) . رشته کاراکتری ASCII با طول متغیر با حداکثر n کاراکتر
NVARCHAR(n) . رشته کاراکتری Unicode با طول متغیر با حداکثر n کاراکتر
• INT . عدد صحیح (زیرمجموعه متناهی از اعداد صحیح که وابسته به ماشین است)
• SMALLINT . عدد صحیح کوچک (زیرمجموعه وابسته به ماشین از نوع صحیح)
DECIMAL(p,d) . عدد ممیز ثابت، با دقت تعریف شده p رقم و با d رقم در سمت راست ممیز
• REAL,DOUBLE precision . اعداد ممیزشناور با دقت مضاعف (وابسته به ماشین)
FLOAT(n) . عدد ممیز شناور با دقت تعریف شده حداقل n رقم
• DATE . تاریخ با فرمت day/month/year

در انتهای هر ستون می توان اطلاعات اضافی داشت. معمول ترین آنها عبارتند از:

PRIMARY KEY یعنی این فیلد کلید اصلی است
NOT NULL یعنی این فیلد باید مقداری داشته باشد و نمی تواند تهی باشد
REFERENCES othertable (primarykeyname) یعنی این فیلد یک کلید خارجی است که در جدول دیگری کلید اصلی است

در انتهای تعریف می توان اطلاعات اضافی دیگری را داشت. برای نمونه:

PRIMARY KEY (column1,column2,...) اگر جدول کلید اصلی ترکیبی دارد باید آنرا در انتهای تعریف مشخص کنید.
FOREIGN KEY (column1,column2,...) REFERENCES othertable اگر جدول ارتباطی با جدول دیگر دارد که یک کلید ترکیبی دارد بنابراین ستون های این جدول که کلید های خارجی هستند باید به این صورت لیست شوند.


مثال. فرمان ایجاد یک جدول به نامemployees با چند فیلد نمونه به صورت زیر می تواند باشد:

CREATE TABLE employees (
id INTEGER PRIMARY KEY
,first_name CHAR(50)
,last_name CHAR(75) NOT NULL
,date_of_birth DATE
);

مثال. تعریف جداول Car و Driver می تواند به صورت زیر باشد:

CREATE TABLE driver (
name varchar(30)
,dob DATE NOT NULL
,PRIMARY KEY (name)
);

CREATE TABLE car (
regno VARCHAR(8)
,make VARCHAR(20)
,colour VARCHAR(30)
,price DECIMAL(8,2)
,owner VARCHAR(30)
,PRIMARY KEY(regno)
,FOREIGN KEY(owner) REFERENCES driver
);


DROP TABLE

عبارت DROP برای از بین بردن یک شیء در پایگاه داده است. فرمان DROP TABLE زمانی بکار می رود که بخواهید جدول را حذف کنید. فرم کلی آن به صورت زیر است:

DROP TABLE tablename;


مثال. فرمان زیر جدول employees را حذف می کند.


DROP TABLE employees;

تنها نکته در حذف یک جدول این است که اگر جدولی توسط کلید خارجی با این جدول در ارتباط باشد نمی توانید آنرا حذف کنید.


مثال. چون جدول car توسط کلید خارجی با جدول driver در ارتباط است می توانید ابتدا جدول Car و سپس Driver را حذف کنید ولی عکس آن نمی شود.

DROP TABLE car;
DROP TABLE driver;


SELECT

معمولا بیشترین عملی که روی پایگاه های داده توسط SQL انجام می گیرد جستجو است، که توسط عبارت SELECT انجام می پذیرد.

دستور SELECT داده ها را از یک یا چند جدول مرتبط بازیابی می کند و اغلب تاثیری روی داده ذخیره شده در پایگاه داده ندارد.

SELECT پیچیده ترین عبارت SQL است. فرم کلی عبارت SELECT به صورت زیر است:

SELECT DISTINCT columns AS columns
FROM table
WHERE rule
GROUP BY columns
HAVING rule
ORDER BY columns;

دستور SELECT دارای چند عبارت اختیاری به شرح زیر است:

• FROM جدول یا جداولی را که از آنها داده بازیابی می شود را مشخص می کند. برای الحاق جداول بر اساس ضابطه خاصی می تواند همراه با عبارت JOIN بیاید.
• WHERE همراه با یک گزاره شرطی برای محدود کردن سطرهای برگردانده شده استفاده می شود.
• GROUP BY اغلب همراه با توابع تجمعی(AVE، SUM، MAX، MIN و COUNT) برای ترکیب یا گروه بندی سطرها یا حذف سطرهای تکراری در مجموعه نتیجه استفاده می شود.
• HAVING همراه با یک گزاره شرطی روی نتیجه GROUP BY کار می کند. توابع تجمعی می توانند در گزاره شرطی HAVING هم استفاده شوند.
• ORDER BY برای تعیین ستون های که بر اساس آنها داده نتیجه مرتب می شود (صعودی و نزولی) .

FROM

در ساده ترین دستور SELECT کلیه سطرهای یک جدول که بعد از عبارت FROM ذکر شده است را بازیابی می کند. لیستی از فیلدهای موردنظر در مقابل عبارت SELECT قرار می گیرد. نام فیلدها با کاما (,) از هم جدا می شوند.

علامت ستاره (*) برای بیان کلیه فیلدهای یک جدول (یا چند جدول) می تواند استفاده شود.


مثال. اسامی کلیه شعبه ها در loan را پیدا کن

SELECT branch_name
FROM loan;

مثال. مشخصات کلیه مشتریان را پیدا کن.

SELECT *
FROM customer;


عبارات محاسباتی +، -، * و / روی یک فیلد در لیست فیلدها می توانند بکاربرده شوند.


مثال. دستور زیر جدولی مشابه loan را بر می گرداند که مقدار صفت خاصه amount آن 10 برابر شده است.

SELECT loan_number, branch_name, amount * 100
FROM loan;


ممکن است لازم باشد داده های موردنیاز را از دو یا چند یک جدول استخراج کنیم.


مثال. اسامی و مقدار وام کلیه مشتریانی را که وامی از شعبه Perryridge گرفته اند را پیدا کن.

SELECT customer_name, borrower.loan_number, amount
FROM borrower, loan
WHERE borrower.loan_number = loan.loan_number AND
     branch_name = 'Perryridge';

مثال. دقت کنید که اگر شرطی ذکر نشود ضرب دکارتی دو جدول حاصل می شود.

SELECT *
FROM borrower, loan;


DISTINCT

SQL اجازه تکرار در نتیجه SELECT را می دهد. بنابراین جدول حاصل ممکن است دارای سطرهای مشابه باشد. اگر این موضوع موردنظر نباشد عبارت DISTINCT را استفاده می کنیم. در این صورت کلیه سطرهای جدول حاصل منحصر بفرد خواهند بود. و سطرهای تکراری حذف می شوند.


مثال. اسامی کلیه شعب بانک که از آنها وامی گرفته شده است را با حذف تکراری ها لیست کن.

SELECT DISTINCT branch_name
FROM loan;

عبارت all مشخص می کند که تکراری ها حذف نشوند.

SELECT ALL branch_name
FROM loan;


WHERE

عبارت WHERE برای انتخاب سطرهای برگردانده شده از دستور SELECT بر طبق شرط خاصی بکار می رود.

برای بیان شرط می توان عملگرهای مقایسه ای (=، !=، <>، >، <، >= و <=) را استفاده کرد.

نتایج مقایسه را می توان توسط عملگرهای منطقی (NOT، AND و OR ) و پرانتز با هم ترکیب کرد. اجرای عملگرهای منطقی به ترتیب الویت آنها است. NOT الویت بالاتر و OR الویت کمتر را دارد. پرانتز می تواند برای تعیین ترتیب انجام عملیات استفاده شود. عمل داخل پرانتز همیشه اول انجام می گیرد.


مثال. کلیه شماره وام هائی که مقدار وام آنها از 1200 بیشتر است را پیدا کن.

SELECT loan_number
FROM loan
WHERE amount > 1200;

مثال. کلیه شماره وام های شعبه Perryridge که مقدار وام آنها از 1200 بیشتر است را پیدا کن.

SELECT loan_number
FROM loan
WHERE amount > 1200 AND branch_name = 'Perryridge';


توجه کنید که هنگام مقایسه با رشته باید آنرا در کوتیشن (' ') قرار داد.


مثال.شماره وام هائی که مقدار وام آنها بین 90,000 و 100,000 می باشد را پیدا کن.

SELECT loan_number
FROM loan
WHERE amount BETWEEN 90000 AND 100000;


عملگر IN برای تعیین اینکه آیا مقدار مشخصی درون مجموعه ای از مقادیر وجود دارد یا خیر بکار می رود.


مثال. مقدار وامهایی که از شعب Perryridge، Downtown یا Redwood گرفته شده اند را پیدا کن.

SELECT amount
FROM loan
WHERE Branch_name IN (' Perryridge' , 'Downtown' , 'Redwood');


هنگام کارکردن با رشته ها وقتی خواهان مطابقت کامل رشته ها نیستیم بلکه بخشی از رشته یا الگوی خاصی از آن بیشتر موردنظر است، می توان از عبارت LIKE به جای علامت (=) استفاده کرد. دو کاراکتر '%' و '_' به ترتیب به معنی یک کاراکتر و بیشتر از یک کاراکتر را برای تطابق می توان بکار برد.


مثال. اسامی کلیه مشتریانی که آدرس آنها شامل کلمه Main است را پیدا کن.

SELECT customer_name
FROM customer
WHERE customer_street LIKE '%Main%';


AS

SQL اجازه تغییر نام جدول را توسط عبارت AS می دهد.


مثال. تعداد وام و مقدار وام کلیه وام ها را پیدا کرده، نام ستون loan_number به loan_id تغییر بده.

SELECT loan_number AS loan_id, amount
FROM loan;

مثال. نام و تعداد وام کلیه مشتریانی که وامی در یک شعبه دارند را پیدا کن.

SELECT customer_name, T.loan_number, S.amount
FROM borrower AS T, loan AS S
WHERE T.loan_number = S.loan_numbe;


توابع تجمعی

توابع تجمعی (aggregation function) عملگرهایی هستند که محاسبه آماری روی گروهی از مقادیر داده ای را انجام می دهند. این توابع روی مقادیر یک ستون از یک جدول عمل می کند و یک مقدار را به عنوان نتیجه بر می گردانند. این توابع شامل AVG، SUM، MAX، MIN و COUNT هستند.

نتیجه تجمع نامی ندارد می تواند از AS برای نامگذاری آن استفاده کرد.


مثال. میانگین موجودی حساب ها در شعبه Perryridge را پیدا کن.

SELECT AVG (balance)
FROM account
WHERE branch_name = 'Perryridge';


COUNT تعداد سطرهای موجود در جواب که حاوی NULL نیستند را می دهد. برای اینکه تعداد مستقل از NULL باشد COUNT(*) را استفاده کنید.


مثال. تعداد مشتریان بانک را محاسبه کن.

SELECT COUNT (*)
FROM customer;


گاهی در جواب تعدادی سطرها مشابه می شوند، اگر می خواهید تعداد سطرهای متمایز را بدست آورید از COUNT DISTINCT استفاده کنید.


مثال. تعداد افرادی که در بانک پول دارند را پیدا کن.

SELECT COUNT (DISTINCT customer_name)
FROM depositor;

مثال. تعداد افرادی که در هر شعبه بانک حساب دارند را پیدا کن.

SELECT branch_name, COUNT (DISTINCT customer_name)
FROM depositor, account
WHERE depositor.account_number = account.account_number
GROUP BY branch_name;


GROUP BY

در بسیاری موارد تحلیل آماری روی گروهی از داده ها موردنیاز است. برای گروه بندی از عبارت GROUP BY استفاده کنید.


مثال. اسامی کلیه شعب و میانگین موجودی حساب آنها را پیدا کن

SELECT branch_name,AVG (balance)
FROM account
GROUP BY branch_name;


HAVING

توابع تجمعی در عبارت WHERE کار نمی کنند. اگر می خواهید با توجه به نتیجه توابع تجمعی شرطی داشته باشید از عبارت HAVING استفاده کنید. HAVING مانند عبارت WHERE کار می کند با این تفاوت که روی آخرین داده حاصل کار می کند و اجازه استعمال توابع تجمعی را هم می دهد. البته هزینه اجرای آن بالاست بنابراین فقط در زمانی که واقعا نیاز است استفاده کنید.


مثال. اسامی کلیه شعب را که میانگین حساب آنها بیشتر از 1200 است را پیدا کن

SELECT branch_name,AVG (balance)
FROM account
GROUP BY branch_name
HAVING AVG (balance) > 1200;


ORDER BY

ترتیب رکوردها در نتیجه پرس و جو معمولا بدون نظم است. اگر می خواهید جدول حاصل دارای نظم خاصی بر طبق یک یا چند فیلد باشد عبارت ORDER BY را به همراه فیلدهای موردنظر اضافه کنید.

برای ترتیب نزولی از DESC و برای ترتیب صعودی از ASC روی هر صفت خاصه استفاده می شود. پیش فرض ترتیب صعودی است.


مثال. اسامی کلیه مشتریانی که وامی در شعبه Perryridge دارند را به ترتیب حروف الفبا لیست کن.

SELECT DISTINCT customer_name
FROM borrower, loan
WHERE borrower loan_number = loan.loan_number AND
     branch_name = 'Perryridge'
ORDER BY customer_nam;


NULL

ممکن است مقدار بعضی از صفات خاصه در رکوردها تهی باشد که توسط NULL مشخص می شود. وقتی فیلدی حاوی NULL است بیان کننده این است که مقدار آن فیلد نامعلوم است یا مقداری در دنیای واقعی ندارد.

عملگرهای مقایسه ای اگر روی NULL عمل کنند مقدار Unknown را برمی گردانند. گزاره IS NULL می تواند برای بررسی مقادیر NULL استفاده شود. عملگر متضاد آن IS NOT است که مقادیری که NULL نیستند را پیدا می کند.

نتیجه هر عبارت ریاضی روی NULL برابر با NULL است. کلیه توابع تجمعی به استثنای COUNT از مقدار NULL صرفنظر می کنند.


مثال. تعداد وام هائی که میزان وام آنها معین نیست را پیدا کن.

SELECT loan_number
FROM loan
WHERE amount IS NULL;


پرس و جوهای تودرتو

در SQL مکانیسمی برای پرس و جوهای تودرتو فراهم شده است. به عبارت دیگر یک عبارت SELECT می تواند درون دیگری قرار بگیرد تا نتیجه اجرای آن در شرط WHERE عبارت SELECT دیگر استفاده شود. عبارت SELECT دوم را یک پرس و جوی فرعی می نامند و حتما باید یک فیلد را برگرداند یعنی فقط یک صفت خاصه در دستور SELECT آن باید باشد.

وقتی حاصل پرس و جوی فرعی بیشتر از یک سطر باشد از عملگرهای ALL، ANY، IN، NOT IN، EXISTS و NOT EXISTS برای گرفتن نتیجه مطلوب باید استفاده کرد.


مثال. اسامی کلیه مشتریانی که هم حساب وهم وام در بانک دارند را پیدا کن.

SELECT DISTINCT customer_name
FROM borrower
WHERE customer_name IN (SELECT customer_name FROM depositor );

مثال. اسامی کلیه مشتریانی که از بانک وام گرفته اند ولی حساب ندارند را پیدا کن.

SELECT DISTINCT customer_name
FROM borrower
WHERE customer_name NOT IN (SELECT customer_name FROM depositor );

مثال. اسامی کلیه مشتریانی که هم حساب وهم وام در شعبه Perryridge دارند را پیدا کن.

SELECT DISTINCT customer_name
FROM borrower, loan
WHERE borrower.loan_number = loan.loan_number AND branch_name = 'Perryridge' AND
branch_name, customer_name IN (SELECT branch_name, customer_name
FROM depositor, account WHERE depositor.account_number = account.account_number );

توجه. پرس و جوهای بالا ساده تر هم می تواند نوشته شود.


ترکیب پرس و جوها

گاهی می خواهیم نتیجه دو پرس و جو را با هم به نحوی ترکیب کنیم و یک جدول را بدست بیاوریم. عملگرهای UNION، INTERSECT و EXCEPT برای ترکیب نتیجه دو پرس و جو می توانند استفاده شوند که به ترتیب مشابه عملگرهای اجتماع، اشتراک و تفاضل در جبر رابطه ای عمل می کنند.

مجموعه فیلدهای دو پرس و جوئی که با هم ترکب می شوند باید از نظر تعداد و نوع مطابق هم باشند.

عملگر UNION جدولی شامل کلیه سطرهای هردو پرس و جو را می دهد. سطرهای تکراری حذف می شوند مگر اینکه از عبارت UNION ALL استفاده شود.

عملگر INTERSECT سطرهای مشترک در نتیجه دو پرس و جو را بر می گرداند. سطرهای تکراری حذف می شوند مگر اینکه از عبارت INTERSECT ALL استفاده شود.

عملگر EXCEPT سطرهائی از نتیجه پرس و جوی اول که در نتیجه پرس و جوی دوم ظاهر نشده است را بر می گرداند. EXCEPT ALL سطرهای تکراری را حذف نمی کند.


مثال. اسامی کلیه مشتریانی که هم حساب وهم وام در بانک دارند را پیدا کن.

SELECT customer_nameFROM borrower
UNION
SELECT customer_name FROM depositor;


JOIN

وقتی بخواهیم اطلاعاتی را از دو جدول بدست بیاوریم می توانیم عمل الحاق را روی دو جدول انجام دهیم. عملگر JOIN رکوردهای گرفته شده از دو جدول را با هم ترکیب می کند و جدول دیگری را به عنوان نتیجه می دهد. شرط الحاق نحوه جفت کردن رکوردهای دو جدول را تعیین می کند.

الحاق دارای انواع مختلفی نظیر الحاق طبیعی و الحاق خارجی است. نوع الحاق تعیین می کند چه رکوردهائی از هر جدول که جفتی در جدول دیگر ندارند در جدول نتیجه باید اضافه شوند.

Natural Join

در الحاق طبیعی کلیه سطرهائی که فیلدهای همنام آنها که در هردو جدول دارای یک مقدار هستند، درنظر گرفته می شود. جدول حاصل تنها شامل یک ستون از ستونهای هم نام خواهد بود.


مثال. اسامی وام گیرنده ها به همراه وام های گرفته شده از بانک را پیدا کنید.

SELECT *
FROM borrower NATURAL JOIN loan;


Outer Join

در الحاق خارجی نیازی نیست رکوردهای دو جدول حتما رکورد مطابقی در جدول دیگر داشته باشند. الحاق خارجی، بسته به جدولی که همه سطرهایش نگهداشته می شود، به سه دسته الحاق چپ، راست و کامل تقسیم می شود.

LEFT OUTER JOIN کلیه مقادیر جدول سمت چپ خود را بعلاوه مقادیری از جدول سمت راست که مطابقت دارند می دهد. RIGHT OUTER JOIN کلیه مقادیر جدول سمت راست خود را می دهد بعلاوه مقادیری از جدول سمت چپ که رکوردهایش جور هستند. FULL OUTER JOIN نتیجه الحاق خارجی چپ و راست را با هم ترکیب می کند.

الحاق خارجی داده های مفقود را، برای سطرهائی که شرط الحاق در آنها برقرار نبوده، با NULL پر می کند.


مثال. اسامی کلیه وام گیرنده ها به همراه میزان وامی که گرفته اند را پیدا کنید.

SELECT *
FROM borrower LEFT OUTER JOIN loan
ON borrower.loan_no = loan.loan_no;

مثال. مقدار کلیه وام های گرفته شده از شعبه Perryridge را به همراه نام وام گیرنده ها پیدا کنید.

SELECT *
FROM borrower RIGHT OUTER JOIN loan
ON borrower.loan_no = loan.loan_no
WHERE loan.branch_name = 'Perryridge';


DELETE

فرمان DELETE اجازه حذف سطرهائی از یک جدول را می دهد. فرم کلی دستور به شکل زیر است:

DELETE FROM table_name WHERE condition;

کلیه رکوردهائی که شرط WHERE در آنها برقرار است از جدول حذف می شوند. اگر شرطی بیان نشود کلیه رکوردهای جدول حذف خواهند شد.

دستور DELETE هیچ رکوردی را به عنوان خروجی بر نمی گرداند.


مثال. کلیه رکوردهای وام گیرندگان را حذف کن.

DELETE FROM borrower;

مثال. کلیه رکوردهایی که حسابی در شعبه Perryridge دارند را حذف کن.

DELETE FROM account
WHERE branch_name = 'Perryridge';


INSERT

دستور INSERT اجازه اضافه کردن رکوردی به یک جدول را می دهد. فرم کلی آن به صورت زیر است:

INSERT INTO table_name
(column_list)
VALUES (value_list);

Column_list لیست فیلدهائی است که مقادیر به آنها نسبت داده خواهد شد و اگر برای همه فیلدها مقداری درنظرگرفته شود می تواند حذف شود. value_list مجموعه ای از مقادیر است که برای هر فیلد در لیست column_list یا فیلدهای جدول که در دستور CREATE TABLE تعریف شده اند مقداری دارد.

تعداد ستون ها و مقادیر آنها باید یکسان باشد. اگر فیلدی ذکر نشود مقدار پیش فرض آن درنظر گرفته می شود.

به فیلدهائی که در دستور CREATE TABLE به عنوان PRIMARY KEY یا با محدودیت NOT NULL تعریف شده اند باید مقداری نسبت داده شود.


مثال. حساب جدیدی را با شماره A-9732 و با موجودی 1200 در شعبه Perryridge اضافه کن.

INSERT INTO account
VALUES ('A-9732', 'Perryridge',1200);
یا
INSERT INTO account
(branch_name, balance, account_number)
VALUES ('A-9732', 'Perryridge',1200);

مثال: اضافه کردن رکورد جدیدی در جدول account با مقدار موجودی null به صورت زیر انجام می شود.

INSERT INTO account
VALUES ('A-777','Perryridge', null );


UPDATE

دستور UPDATE اجازه تغییر داده های درون یک جدول را می دهد. این دستور هیچ رکوردی را اضافه یا حذف نمی کند. شکل کلی آن به صورت زیر است:

UPDATE table_name
SET column_name = value, column_name=value, ...
WHERE condition;

در کلیه رکوردهائی که شرط در آنها برقرار بوده است مقدار فیلدی که نامش در عبارت SET تعیین برابر با مقدار جدید می شود. دستور UPADTE ممکن است روی یک یا چند رکورد در یک جدول تاثیر بگذارد.


مثال. حساب هائی که موجودی آنها بیشتر از 10000 است را به میزان 6% افزایش بده.

UPDATE account
SET balance = balance * 1.06
WHERE balance > 10000;


ایرادهای SQL

به چند نمونه از انتقادهائی که درباره استفاده کاربردی از SQL وجود دارد اشاره می شود:

• پیاده سازی های مختلفی از SQL توسط سازندگان DBMS وجود دارد که گاهی با هم متناقض و نا موافق است. خصوصا مواردی نظیر فرمت زمان و تاریخ، الحاق رشته ها، مقادیر تهی و حساسیت به متن در مقایسه از یک سازنده به دیگری ممکن است متفاوت باشد.
• نوشتن شرط اشتباه در الحاق جداول به راحتی ضرب دکارتی دو جدول را نتیجه می دهد که به ندرت ممکن است در عمل سودمند باشد.
• ممکن است عبارت شرط در بهنگام سازی و حذف اشتباهی ساخته شود و روی کلیه سطرهای جدول ناخواسته تاثیر بگذارد.
• SQL و مدل رابطه ای راهی برای حمایت ساختارهای درختی و ارجاع بازگشتی به سطرهای دیگر یک جدول ندارند.

_____________________________________________

نرمال سازی


 

این فصل مروری بر تئوری نرمالسازی پایگاه داده ها می باشد و روی چهار فرم اول از هفت فرم شناخته شده نرمال تمرکز دارد.

فرم های نرمال
First Normal Form (1NF)
Second Normal Form (2NF)
Third Normal Form (3NF)
Forth Normal Form (4NF)
معایب نرمالسازی


نرمالسازی فرآیند سازماندهی داده در پایگاه داده بطور کارآمد است. نرمالسازی روشی برای طراحی جداول پایگاه داده است و داده ها را به طریقی ساماندهی می کند که باعث کاهش افزونگی داده و رفع مشکلات ساختاری و آنومالی شود.

هدف از نرمالسازی حذف افزونگی داده و باقی نگهداشتن وابستگی بین داده های مرتبط است. به این طریق اندازه پایگاه داده را کاهش داده و ذخیره منطقی داده را تضمین می کند.

مفهوم نرمالسازی پایگاه داده اولین با ر توسط Edgar Frank Codd معرفی شد.

فرآیند نرمالسازی شامل ایجاد جداول و برقراری ارتباط بین آنها طبق قواعد معین است و روی وابستگی های ستون های جدول تمرکز دارد. این فرآیند اغلب باعث ایجاد جداول بیشتر می شود ولی باوجودیکه اثر تکرار داده درون پایگاه داده را دارد باعث افزونگی غیر ضروری داده نمی شود. هدف از نرمالسازی تضمین این است که ستون های غیر کلیدی در هر جدول مستقیما وابسته به کل کلید باشند و به این ترتیب حذف وابستگی های ناسازگار، کاهش افزونگی، آنومالی کمتر و بهبود کارائی را نتیجه می دهد.


مثال. جدول زیر که اطلاعات مربوط به خرید مشتریان را دارد درنظر بگیرید:

An Ugly Big Table

همانطور که مشاهده می شود با هر فروش داده ها در جدول تکرار می شوند. این افزونگی مشکلات زیر را می تواند ایجاد کند:

• هدر رفتن فضای ذخیره سازی. با وجودیکه امروزه دیسک های چندصد گیگا بایتی وجود دارد چندین بار ذخیره یک داده غیر ضروری است.
• آنومالی در بهنگام سازی . اگر داده یک مشتری، مثلا آدرس، تغییر کند باید در همه جاهائی که ذخیره شده است این تغییر اعمال شود درغیراینصورت جامعیت نقص می شود.
• آنومالی در حذف. اگر این جدول به منظور نگهداری مشخصات مشتریان باشد، اگر مشتری خریدش را پس بدهد و سطر مربوط به آن حذف شود کلیه اطلاعات مشتری هم حذف می شود.
• آنومالی در درج. به همین صورت نمی توانیم مشخصات مشتری جدید را درج کنیم مگر اینکه کالائی خریده باشد.

جدا کردن داده های جدول فوق به جداول جداگانه افزونگی را کاهش می دهد و مواجهه با آنومالی های فوق را ساده تر می کند. این فرآیند را نرمالسازی می نامند.


فرم های نرمال

تئوری پایگاه داده درجه نرمالسازی جدول را با اصطلاح فرم های نرمال(normal form) شرح می دهد. فرم های نرمال (یا بطور خلاصه NF) معیاری برای تعیین درجه نرمال جدول دراختیار می گذارد.

فرم های نرمال جداگانه روی هر جدول می توانند بکار بروند. پایگاه داده زمانی در فرم نرمال n خواهد بود که کل جداول آن در فرم نرمال n باشند.

فرم های نرمال عبارتند از:

• First Normal Form (1NF)
• Second Normal Form (2NF)
• Third Normal Form (3NF)
• Forth Normal Form (4NF)
• Boyce/Codd Normal Form (BCNF)
• Fifth Normal Form (5NF)
• Domain/Key Normal Form (DKNF)

اگر فرم اول نرمال در جدولی مشاهده شود اصطلاحا آنرا در فرم اول نرمال (1NF) می نامند. اگر سه فرم اول نرمال دیده شود آنرا در فرم سوم نرمال (3NF) درنظر می گیرند. جدولی که دارای فرم نرمال درجه بالاتر باشد فرم های نرمال درجه پائین تر را هم دارا می باشد. بنابراین مثلا اگر جدولی 3NF باشد 2NF و 1NF هم هست. ولی عکس این صحت ندارد.

توجه داشته باشید که نرمالسازی یک فرآیند تکراری نیست. یک جدول ممکن است در یک مرحله به فرم سوم نرمال دربیاید. بعلاوه اگر 3NF باشد به احتمال بسیار زیاد 5NF هم خواهد بود.

فرم نرمال هریک باعث کاهش بیشتر افزونگی و تقسیم جداول به واحدهای کوچکتر می شوند. سه فرم اول نرمال (1NF، 2NF و 3NF) در ابتدا توسط Codd تعریف شد که به طور خلاصه وابستگی صفات خاصه غیر کلید را به کلید الزام می کنند. فرم های چهارم و پنجم (4NF و 5NF) با ارتباطات چند به چند و یک به چند بیت صفات خاصه سروکار دارند. دو فرم دیگر هم وجود دارد که کاملا با این جریان جور نمی شوند که BCNF و DK/NF هستند.

در برنامه های کاربردی اغلب 1NF، 2NF و 3NF و گاهی 4NF و 5NF دیده خواهند شد 5NF بندرت مشاهده می شود به همین دلیل در اینجا توضیح داده نمی شود.


(1NF) First Normal Form

یک جدول در فرم اول نرمال (1NF) است اگر و فقط اگر فاقد گروه داده تکرار شونده باشد. به عبارت دیگر هر ستون در جدول دارای مقدار اتمیک باشد.

در مدل رابطه ای هر جدولی حداقل در فرم اول نرمال هست زیرا از الزامات مدل این است که هر جدول شامل دقیقا یک مقدار برای هر صفت خاصه باشد که اصطلاحا "فاقد گروه تکرار شونده" گفته می شود.


مثال. جدول ALL_SALES که اطلاعات فروش را نگهداری می کند درنظر بگیرید. این جدول در فرم اول نرمال هست چون هیچ کدام از ستون ها چندمقداری نیستند بنابراین نیازی نیست روی جدول کاری انجام دهیم بجز اینکه یک کلید انتخاب نمائیم. ترکیب غیر تکراری ProductNo+CustomerNo+SaleNo را می توان کلید اصلی درنظر گرفت.

ALL_SALES(SaleNo, ProductNo, CustomerNo, SaleDate, QtyInStock, Description, Price, Customer_Name, Customer_Address, CreditLimit, Amount, Salesrep)


(2NF) Second Normal Form

یک جدول در فرم دوم نرمال (2NF) است اگر اولا 1NF باشد و ثانیا کلیه ستون های غیرکلید با کلید اصلی وابستگی تابعی کامل داشته باشند.

ستون Y با ستون X در یک رابطه وابستگی تایعی (functional dependency) دارد اگروفقط اگر به ازای هر مقدار در X دقیقا یک مقدار در Y متناظر با آن وجود داشته باشد. که به صورت X→Y نشان داده می شود.

مثال. در جدول ALL_SALES مثال قبل، Customer_Address با CustomerNo وابستگی تابعی دارد، زیرا یک مشتری خاص تنها با یک آدرس مربوط است. توجه کنید که عکس آن برقرار نیست و چند مشتری ممکن است در یک آدرس زندگی کنند. بنابراین یک آدرس ممکن است با بیش از یک شماره مشتری در ارتباط باشد. اگر مشتری بیش از یک آدرس داشته باشد دیگری وابستگی تابعی با شماره مشتری ندارد.

ستون Y روی مجموعه صفات خاصه X وابستگی تابعی کامل (Full functional dependency) دارد اگر روی X وابستگی تابعی داشته باشد و با هیچ زیرمجموعه ای از X وابستگی تابعی نداشته باشد.

مثال. در جدول ALL_SALES مثال قبل آدرس مشتری وابستگی کامل با SaleNo، ProductNo و CustomerNo دارد ولی وابستگی تابعی کامل ندارد چون با CustomerNo وابستگی تابعی دارد.

توجه کنید اگر کلیدهای کاندید در جدول ترکیبی نباشند یعنی تنها شامل یک ستون باشند بلافاصله می گوئیم جدول 2NF است.


مثال. جدول ALL_SALES را درنظر بگیرید:

ALL_SALES(SaleNo, ProductNo, CustomerNo, SaleDate, QtyInStock, Description, Price, Customer_Name, CreditLimit, Amount, Salesrep)

مشاهده می شود بعضی از ستون ها بهم مرتبط هستند و توسط بخشی از کلید مشخص می شوند. به عبارت دیگر بعضی ستون ها با زیرمجموعه ای از کلید وابستگی تابعی دارند:

ProductNo → {Description, ReorderLevel, Price, QtyInStock}
CustomerNo → {Customer_Name, CreditLimit}
SaleNo → {Date, CustomerNo, ProductNo, Qty, Amount, Salesrep}

با جدا کردن این ستون ها به جداول جداگانه به فرم دوم نرمال می رسیم.

PRODUCT(ProductNo, Description, Price, QtyInStock)
CUSTOMER(CustomerNo, Customer_Name, CreditLimit)
SALE(SaleNo, Date, CustomerNo, ProductNo, Qty, Amount, Salesrep)


(3NF) Third Normal Form

یک جدول در فرم سوم نرمال (3NF) است اگر اولا 2NF باشد، ثانیا کلیه صفات خاصه غیر کلید در جدول با کلید اصلی وابستگی تابعی غیر تعدی داشته باشند.

وابستگی تعدی (transitive dependency) یک وابستگی تابعی غیر مستقیم است که در آن X→Z است اگر X→Y و Y→Z باشد.

در فرم سوم نرمال کلیه ستون های جدول مستقیما توسط کلید اصلی مشخص می شوند. با حذف فیلدهائی که وابستگی مستقیم با کلید ندارند به فرم سوم نرمال می رسیم. برای این کار گروهی از ستون های جدول را که مقدارشان برای بیش از یک رکورد تکرار می شود را در جدول جداگانه ای قرار دهید.


مثال. فرض کنید جدول PRODUCT به صورت زیر جزئیات تولید کننده هر محصول را دارا باشد:

PRODUCT(ProductNo, Description, ReorderLevel, Price, QtyInStock, SupplierCode, SupplierName, SupplierAddress)

این جدول کلید اصلی تک ستونی دارد بنابراین 2NF است. اگر تولید کننده چندین محصول را تولید کند فیلدهای SupplierName و SupplierAddress برای هر محصول تکرار می شود زیرا وابستگی تعدی با کلید اصلی دارند.

ProductNo → SupplierCode → {SupplierName, SupplierAddress}

با حذف این ستون ها و تقسیم جدول به صورت زیر به فرم سوم نرمال می رسیم. توجه کنید که SupplierCode در جدول PRODUCT به عنوان کلید خارجی باقی می ماند.

PRODUCT(ProductNo, Description, ReorderLevel, Price, QtyInStock, SupplierCode)
SUPPLIER(SupplierCode, SupplierName, SupplierAddress)


رسیدن به فرم سوم نرمال اگرچه مطلوب است ولی همیشه عملی نیست. جداول متعدد باعث تنزل کارائی پرس و جوها می شود. بنابراین ممکن است فرم سوم تنها روی ستون هائی از جدول که زیاد تغییر می کنند اعمال شود و برای فیلدهای وابسته ای باقی مانده برنامه به نحوی طراحی می شود که کاربر ملزم باشد کلیه فیلدهای مرتبط را درهراصلاح بازبینی کند.

(4NF) Fourth Normal Form

یک جدول در فرم چهارم نرمال (4NF) است اگر اولا 3NF باشد، ثانیا هیچ ستونی در جدول وابستگی چند مقداری نداشته باشد.

وابستگی چندمقداری (multivalued dependency) به این معنی است که حضور رکوردهای معینی در جدول وجود رکوردهای معین دیگری را برساند.


مثال. اگر مشتریانی با چند آدرس داشته باشیم (که در محیط تجارت عادی است)، در جدول CUSTOMER نمی توانیم چند ستون آدرس را اضافه کنیم چون تعداد آدرس های ممکن را نمی دانیم. بنابراین ناگزیر به اضافه کردن رکورد جدید برای هر آدرس مشتری هستیم که باعث تکرار و افزونگی داده می شود. زیرا CustomerNo دیگر تنها یک آدرس را معین نمی کند بلکه مجموعه ای از آدرس های را نشان می دهد به عبارت دیگر وابستگی چندمقداری دارد. با حذف چنین وابستگی هائی و تقسیم جدول به صورت زیر به فرم چهارم نرمال می رسیم.

CUSTOMER(CustomerNo, First, Last, CreditLimit)
CUSTOMER_ADDRESS(CustomerNo, Address)

حالا هر مشتری می تواند هر تعداد آدرسی را داشته باشد.


معایب نرمالسازی

نرمالسازی تکنیک مهمی برای طراحی پایگاه داده های کارآمد است اما در ضمنی که افزونگی داده را کاهش می دهد سبب کاهش اجرای سیستم می شود. درجات بالای نرمال معمولا جدوال بیشتر را می طلبند. برای پاسخ به پرس و جوها گاهی باید کلیه جداول تقسیم شده دوباره با هم الحاق شوند که در کاربردهائی که زمان پاسخ مهم است (نظیر وب) مطلوب نیست.

بالاترین سطح نرمالسازی با توجه به عملیات کاربردی درنظر گرفته می شود. در پایگاه داده هایی که بیشتر خواندنی هستند و افزونگی داده در آنها مشکل حادی نیست، مانند داده های کاتالوگ یک سایت تجارت الکترونیکی، می توان سطح نرمالسازی را کاهش داد. به این عمل denormalization می گویند. از طرف دیگر در کاربردهائی که درگیر داده های مهم مانند داده های مالی هستند که دائما در حال تغییرند و باید سازگار باقی بمانند، احتمالا سعی می شود به سطوح بالاتر نرمال برسند حتی اگر سرعت پایگاه داده کم شود.

گاهی با توجه به وضعیت ممکن است داده ها از چند پایگاه داده نرمال شده استخراج شوند و در یک انبار داده غیر نرمال قرار گیرد. این روش برای مخزن داده Data warehouse استاندارد خوبی است.