π― What is Domain Constraints?
A Domain Constraint restricts the set of valid values that an attribute (column) in a table can take.
It ensures that the data entered is appropriate, meaningful, and valid according to the attribute's data type and rules.
A Domain Constraint specifies that the value of every attribute must be drawn from a defined domain (set of permissible values).
π― Purpose of Domain Constraints:
β Prevent invalid data from being entered
π Enforce data consistency
π Help in data validation
π Ensure values are appropriate to the field
π§Ύ Examples of Domain Constraints
Column | Allowed Domain (Constraint) | Example Valid Values |
|---|---|---|
| Integer between 0 and 120 |
|
| String with email format |
|
| Only |
|
| Date only |
|
| 10-digit number |
|
π§ͺ Example SQL Implementation:
CREATE TABLE Student (
StudentID INT PRIMARY KEY,
Name VARCHAR(50),
Age INT CHECK (Age >= 0 AND Age <= 120),
Gender VARCHAR(10) CHECK (Gender IN ('Male', 'Female', 'Other')),
Email VARCHAR(100)
);<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Domain Constraints β Try It Yourself</title>
<style>
.infographic-domainconstraint {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--bad: #dc2626;
--bad-soft: #fee2e2;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 1020px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-domainconstraint[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--bad: #f87171;
--bad-soft: #3a1414;
}
.infographic-domainconstraint * { box-sizing: border-box; }
.dc-head { text-align: center; margin-bottom: 0.25rem; }
.dc-head h2 {
font-family: var(--display-font);
font-size: 1.9rem;
margin: 0 0 0.5rem;
}
.dc-head p {
color: var(--ink-soft);
font-size: 1rem;
margin: 0 auto;
max-width: 640px;
line-height: 1.55;
}
.dc-frame {
background: var(--paper-alt);
border: 1px solid var(--line);
border-radius: 10px;
padding: 1.25rem;
margin-top: 1.75rem;
}
.dc-frame-title {
font-family: var(--display-font);
font-size: 1.05rem;
margin: 0 0 0.85rem;
}
.dc-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.dc-table {
width: 100%;
min-width: 680px;
border-collapse: collapse;
background: var(--paper);
border-radius: 8px;
font-size: 0.85rem;
}
table.dc-table th, table.dc-table td {
border: 1px solid var(--line);
padding: 0.5rem 0.65rem;
text-align: left;
white-space: nowrap;
}
table.dc-table th { background: var(--accent); color: #fff; font-weight: 700; font-size: 0.72rem; }
table.dc-table td.is-null { color: var(--ink-soft); font-style: italic; }
table.dc-table tr.is-new td { animation: dc-row-in 0.5s ease; }
@keyframes dc-row-in { from { background: var(--good-soft); } to { background: transparent; } }
.dc-form {
margin-top: 1.1rem;
padding-top: 1.1rem;
border-top: 1px dashed var(--line);
}
.dc-form-title { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); margin: 0 0 0.7rem; }
.dc-form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 0.6rem;
margin-bottom: 0.85rem;
}
.dc-field label { display: block; font-size: 0.72rem; color: var(--ink-soft); margin-bottom: 0.25rem; }
.dc-field input {
width: 100%;
font: inherit;
font-size: 0.85rem;
padding: 0.5rem 0.6rem;
border: 1px solid var(--line);
border-radius: 6px;
background: var(--paper);
color: var(--ink);
}
.dc-field input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.dc-field .dc-hint { font-size: 0.66rem; color: var(--ink-soft); margin-top: 0.2rem; }
.dc-add-btn {
font: inherit;
font-size: 0.88rem;
background: var(--accent);
color: #fff;
border: none;
border-radius: 7px;
padding: 0.6rem 1.2rem;
cursor: pointer;
}
.dc-add-btn:hover { opacity: 0.9; }
.dc-msg {
margin-top: 0.9rem;
padding: 0.7rem 0.9rem;
border-radius: 8px;
font-size: 0.85rem;
line-height: 1.55;
display: none;
}
.dc-msg.is-visible { display: block; }
.dc-msg.msg-bad { background: var(--bad-soft); color: var(--bad); }
.dc-msg.msg-good { background: var(--good-soft); color: var(--good); }
.dc-chips {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: center;
margin-top: 1.75rem;
}
.dc-chip {
font-size: 0.73rem;
background: var(--paper-alt);
border: 1px solid var(--line);
border-radius: 999px;
padding: 0.4rem 0.8rem;
color: var(--ink-soft);
transition: background 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
}
.dc-chip.is-hit {
background: var(--accent);
color: #fff;
border-color: var(--accent);
transform: scale(1.08);
}
@media (prefers-reduced-motion: reduce) {
.infographic-domainconstraint *, .infographic-domainconstraint *::before, .infographic-domainconstraint *::after {
transition-duration: 0.001ms !important;
animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-domainconstraint" id="domainconstraint">
<div class="dc-head">
<h2>Domain Constraints β Try It Yourself</h2>
</div>
<div class="dc-frame">
<p class="dc-frame-title">π Student</p>
<div class="dc-table-scroll">
<table class="dc-table" id="dcTable"></table>
</div>
<div class="dc-form">
<p class="dc-form-title">Add a student</p>
<div class="dc-form-grid">
<div class="dc-field"><label for="dcId">StudentID</label><input id="dcId" type="text" placeholder="e.g. 3"></div>
<div class="dc-field"><label for="dcName">Name</label><input id="dcName" type="text" placeholder="e.g. Chloe"></div>
<div class="dc-field">
<label for="dcAge">Age</label>
<input id="dcAge" type="text" placeholder="0β120">
<div class="dc-hint">Integer, 0β120</div>
</div>
<div class="dc-field">
<label for="dcEmail">Email</label>
<input id="dcEmail" type="text" placeholder="name@domain.com">
<div class="dc-hint">Must match email format</div>
</div>
<div class="dc-field">
<label for="dcGender">Gender</label>
<input id="dcGender" type="text" placeholder="Male / Female / Other">
<div class="dc-hint">One of three values</div>
</div>
<div class="dc-field">
<label for="dcDob">DOB</label>
<input id="dcDob" type="text" placeholder="YYYY-MM-DD">
<div class="dc-hint">Date only</div>
</div>
<div class="dc-field">
<label for="dcPhone">Phone</label>
<input id="dcPhone" type="text" placeholder="10 digits">
<div class="dc-hint">Exactly 10 digits</div>
</div>
</div>
<button class="dc-add-btn" id="dcAdd" type="button">Add Student</button>
<div class="dc-msg" id="dcMsg"></div>
</div>
</div>
<div class="dc-chips" id="dcChips">
<span class="dc-chip" data-chip="age">Integer range (Age)</span>
<span class="dc-chip" data-chip="email">Pattern match (Email)</span>
<span class="dc-chip" data-chip="gender">Enumerated values (Gender)</span>
<span class="dc-chip" data-chip="dob">Date format (DOB)</span>
<span class="dc-chip" data-chip="phone">Fixed-length numeric (Phone)</span>
<span class="dc-chip" data-chip="null">NULL passes any domain</span>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('domainconstraint');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
let students = [
{ id: '1', name: 'Alice', age: '25', email: 'alice@gmail.com', gender: 'Female', dob: '2005-06-12', phone: '9876543210' },
{ id: '2', name: 'Bob', age: '22', email: 'bob@gmail.com', gender: 'Male', dob: '2003-01-15', phone: '9123456780' }
];
let lastNew = -1;
const allowedGenders = ['male', 'female', 'other'];
const table = document.getElementById('dcTable');
const msg = document.getElementById('dcMsg');
const chips = document.querySelectorAll('.dc-chip');
function showMsg(text, type) {
msg.textContent = text;
msg.className = 'dc-msg is-visible msg-' + type;
}
function hitChip(n) {
chips.forEach(c => c.classList.remove('is-hit'));
const ids = Array.isArray(n) ? n : [n];
ids.forEach(id => {
const chip = document.querySelector('.dc-chip[data-chip="' + id + '"]');
if (chip) chip.classList.add('is-hit');
});
}
function cell(val) {
return (val === '' || val === undefined) ? '<td class="is-null">NULL</td>' : '<td>' + val + '</td>';
}
function render() {
let html = '<thead><tr><th>StudentID</th><th>Name</th><th>Age</th><th>Email</th><th>Gender</th><th>DOB</th><th>Phone</th></tr></thead><tbody>';
students.forEach((s, i) => {
html += '<tr' + (i === lastNew ? ' class="is-new"' : '') + '>' +
cell(s.id) + cell(s.name) + cell(s.age) + cell(s.email) + cell(s.gender) + cell(s.dob) + cell(s.phone) + '</tr>';
});
html += '</tbody>';
table.innerHTML = html;
}
function isValidDate(str) {
if (!/^\d{4}-\d{2}-\d{2}$/.test(str)) return false;
const d = new Date(str);
return !isNaN(d.getTime()) && str === d.toISOString().slice(0, 10);
}
document.getElementById('dcAdd').addEventListener('click', () => {
const id = document.getElementById('dcId').value.trim();
const name = document.getElementById('dcName').value.trim();
const age = document.getElementById('dcAge').value.trim();
const email = document.getElementById('dcEmail').value.trim();
const gender = document.getElementById('dcGender').value.trim();
const dob = document.getElementById('dcDob').value.trim();
const phone = document.getElementById('dcPhone').value.trim();
if (!id) { showMsg('β StudentID can\u2019t be empty β it\u2019s the primary key for this table.', 'bad'); return; }
if (students.some(s => s.id === id)) { showMsg('β StudentID ' + id + ' already exists β primary key values must be unique.', 'bad'); return; }
if (age !== '') {
const ageNum = Number(age);
if (!/^\d+$/.test(age) || ageNum < 0 || ageNum > 120) {
hitChip('age');
showMsg('β Age "' + age + '" is outside its domain β Age must be an integer between 0 and 120.', 'bad');
return;
}
}
if (email !== '') {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
hitChip('email');
showMsg('β "' + email + '" isn\u2019t a valid Email β it must match the format name@domain.com.', 'bad');
return;
}
}
if (gender !== '') {
if (!allowedGenders.includes(gender.toLowerCase())) {
hitChip('gender');
showMsg('β "' + gender + '" isn\u2019t in Gender\u2019s domain β only \'Male\', \'Female\', or \'Other\' are allowed.', 'bad');
return;
}
}
if (dob !== '') {
if (!isValidDate(dob)) {
hitChip('dob');
showMsg('β "' + dob + '" isn\u2019t a valid DOB β dates must be real and formatted as YYYY-MM-DD.', 'bad');
return;
}
}
if (phone !== '') {
if (!/^\d{10}$/.test(phone)) {
hitChip('phone');
showMsg('β "' + phone + '" isn\u2019t a valid Phone β it must be exactly 10 digits.', 'bad');
return;
}
}
students.push({ id, name, age, email, gender, dob, phone });
lastNew = students.length - 1;
render();
const blanks = [age, email, gender, dob, phone].some(v => v === '');
if (blanks) {
hitChip('null');
showMsg('βοΈ Row added. Any field left blank is stored as NULL β which automatically satisfies its domain constraint, since there\u2019s no value to check.', 'good');
} else {
hitChip(['age', 'email', 'gender', 'dob', 'phone']);
showMsg('βοΈ Row added β every field matched its column\u2019s domain: a valid age, email format, gender, date, and phone number.', 'good');
}
document.getElementById('dcId').value = '';
document.getElementById('dcName').value = '';
document.getElementById('dcAge').value = '';
document.getElementById('dcEmail').value = '';
document.getElementById('dcGender').value = '';
document.getElementById('dcDob').value = '';
document.getElementById('dcPhone').value = '';
});
render();
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});π§© What Makes Up a Domain?
A domain can be defined by:
Data type (e.g., INT, VARCHAR, DATE)
Size/Length (e.g., VARCHAR(50))
Permissible values (e.g.,
CHECK (Grade IN ('A', 'B', 'C')))Constraints (e.g., NOT NULL, CHECK)
β Summary:
Feature | Description |
|---|---|
π Definition | Limits values in a column to valid data |
π§ Based on | Data type, format, length, condition |
βοΈ Implemented using | Data types + |
β Prevents | Invalid, illogical, or out-of-range data |