Lab 10: Schema Objects & Data Dictionary¶
Objectives:¶
- Understand and create views (
CREATE VIEW) to simplify and restrict data access. - Understand how SQL Server's indexed views relate to the "materialized view" concept used in other database systems.
- Understand auto-numbering using
IDENTITYcolumns andCREATE SEQUENCE. - Create indexes and understand the difference between clustered and non-clustered indexes.
- Create synonyms for schema objects.
- Query the system data dictionary (
sys.tables,sys.columns,INFORMATION_SCHEMA.COLUMNS).
Activity Outcomes:¶
- Create a view that hides sensitive columns from a base table.
- Create an index and identify a query that benefits from it.
- Query
INFORMATION_SCHEMA.COLUMNSto inspect a table's structure. - Create and use a synonym.
Tools / Software Required:
- SQL Server 2019 (Developer or Express edition)
- SQL Server Management Studio (SSMS)
- The HR sample database (REGIONS, COUNTRIES, LOCATIONS, DEPARTMENTS, JOBS, EMPLOYEES, JOB_HISTORY)
Instructor Note: As pre-lab activity, read the chapter on "Schema Objects: Views, Indexes, Sequences and the Data Dictionary" from the course's SQL Server reference text.
1) Useful Concepts¶
| Object / Statement | Description |
|---|---|
CREATE VIEW view_name AS SELECT ... |
Defines a virtual table backed by a stored query; does not store data itself |
| Indexed View (SQL Server) | SQL Server's equivalent of a "materialized view" -created with CREATE VIEW ... WITH SCHEMABINDING followed by a unique clustered index on the view, which physically stores the result set |
IDENTITY(seed, increment) |
Column property that auto-generates sequential numeric values on INSERT (most common T-SQL auto-increment mechanism) |
CREATE SEQUENCE seq_name AS INT START WITH 1 INCREMENT BY 1 |
A standalone, reusable number generator independent of any single table (closer to Oracle-style sequences) |
NEXT VALUE FOR seq_name |
Retrieves the next value from a sequence |
CREATE INDEX idx_name ON table(column) |
Creates a non-clustered index to speed up lookups on a column |
CREATE CLUSTERED INDEX |
Creates an index that determines the physical storage order of table rows (a table may have only one) |
CREATE NONCLUSTERED INDEX |
Creates a separate structure with pointers back to the data rows; a table may have many |
CREATE SYNONYM syn_name FOR schema.object |
Creates an alternate name for a table, view, or other object |
sys.tables |
System catalog view listing all user tables |
sys.columns |
System catalog view listing all columns of all objects |
INFORMATION_SCHEMA.COLUMNS |
ANSI-standard view exposing column metadata (name, type, nullability) for every table |
2) Solved Lab Activities¶
| Sr. No. | Allocated Time | Level of Complexity | CLO Mapping |
|---|---|---|---|
| Activity 1 | 15 Minutes | Low | CLO-3 |
| Activity 2 | 15 Minutes | Medium | CLO-3 |
| Activity 3 | 15 Minutes | Low | CLO-3 |
| Activity 4 | 15 Minutes | Low | CLO-3 |
Activity 1: Creating a simplified employee-department view¶
HR staff need a simplified, read-only view of employees and their departments that hides sensitive columns such as salary and commission_pct. Create a view EMPLOYEE_DIRECTORY_VW exposing only the employee's name, email, job, and department name.
Solution:
CREATE VIEW EMPLOYEE_DIRECTORY_VW AS
SELECT
e.employee_id,
e.first_name,
e.last_name,
e.email,
e.job_id,
d.department_name
FROM EMPLOYEES e
JOIN DEPARTMENTS d ON e.department_id = d.department_id;
Output / Expected behaviour:
Command(s) completed successfully.
SELECT * FROM EMPLOYEE_DIRECTORY_VW WHERE department_name = 'IT';
| employee_id | first_name | last_name | email | job_id | department_name |
|-------------|------------|-----------|----------------|-----------|------------------|
| 103 | Alexander | Hunold | AHUNOLD | IT_PROG | IT |
| 104 | Bruce | Ernst | BERNST | IT_PROG | IT |
-- salary and commission_pct are not exposed through this view.
Activity 2: Creating an index and observing its use¶
Employee lookups by last_name are frequent and slow on a large EMPLOYEES table. Create a non-clustered index on last_name and write a query that would use it.
Solution:
CREATE NONCLUSTERED INDEX idx_employees_lastname
ON EMPLOYEES (last_name);
GO
-- Query that benefits from the new index:
SELECT employee_id, first_name, last_name, department_id
FROM EMPLOYEES
WHERE last_name = 'King';
Output / Expected behaviour:
Command(s) completed successfully.
| employee_id | first_name | last_name | department_id |
|-------------|------------|-----------|----------------|
| 100 | Steven | King | 90 |
-- The query's execution plan shows an "Index Seek" on idx_employees_lastname
-- instead of a full table scan, because the WHERE clause filters on last_name.
Activity 3: Querying INFORMATION_SCHEMA for column metadata¶
Before writing a report query, a developer wants to see every column of the EMPLOYEES table, along with its data type and whether it allows NULLs.
Solution:
SELECT
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'EMPLOYEES'
ORDER BY ORDINAL_POSITION;
Output / Expected behaviour:
| COLUMN_NAME | DATA_TYPE | CHARACTER_MAXIMUM_LENGTH | IS_NULLABLE |
|----------------|-----------|--------------------------|-------------|
| employee_id | int | NULL | NO |
| first_name | nvarchar | 50 | YES |
| last_name | nvarchar | 50 | NO |
| email | nvarchar | 100 | NO |
| phone_number | varchar | 20 | YES |
| hire_date | date | NULL | NO |
| job_id | varchar | 10 | NO |
| salary | decimal | NULL | YES |
| commission_pct | decimal | NULL | YES |
| manager_id | int | NULL | YES |
| department_id | int | NULL | YES |
Activity 4: Creating a synonym¶
Report writers keep mistyping the full table name EMPLOYEES in ad-hoc queries. Create a shorter synonym EMP for it.
Solution:
CREATE SYNONYM EMP FOR dbo.EMPLOYEES;
-- Usage:
SELECT employee_id, first_name, last_name FROM EMP WHERE department_id = 60;
Output / Expected behaviour:
Command(s) completed successfully.
| employee_id | first_name | last_name |
|-------------|------------|-----------|
| 103 | Alexander | Hunold |
| 104 | Bruce | Ernst |
3) Graded Lab Tasks¶
Note: The instructor may adjust these tasks to the level of difficulty and complexity of the solved activities. Tasks should be evaluated in the same lab session.
Lab Task 1: Department summary view
Create a view DEPARTMENT_HEADCOUNT_VW that lists each department's department_name along with a count of employees in it (hint: use GROUP BY with JOIN).
Lab Task 2: Indexing for a search column
Create a non-clustered index on the email column of EMPLOYEES, then write a query that looks up an employee by email and would benefit from this index.
Lab Task 3: Data dictionary and synonym
Write a query against sys.tables that lists every user table in the database along with its create_date. Then create a synonym DEPT for the DEPARTMENTS table and use it in a simple SELECT.