🚧 Under construction — VoTechWorks is being built. A free tech program — complimentary, as our commitment to get America working.
voTechWorksGrade 13 · a vocational technology learning center, by urbanicity
newSchoolWorks.com › VoTechWorks › Technology & Design › Data Science & Analytics › SQL and PostgreSQL for Data Analytics › Lesson 6
TEC-DATA85-04 · Lesson 6 · 11 clock hours · lab

Data Import, Export, and Integrity Constraints

Objective. Students load data from CSV and JSON sources into PostgreSQL using COPY and INSERT, enforce NOT NULL, UNIQUE, CHECK, and foreign-key constraints, and export query results in multiple formats.

⚠ Pending professional review

This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.

VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.

Data Import, Export, and Integrity Constraints

Why This Lesson Matters

Real-world data rarely arrives clean or in the exact format a database expects. As a data analyst, you will spend a significant portion of your time loading data from external sources, fixing the problems that surface during loading, and setting up guardrails so that bad data cannot enter the database in the first place. PostgreSQL provides powerful tools for all three tasks: the `COPY` command for bulk loading and exporting, and a set of constraint types that enforce data quality rules at the database level.

---

Bulk Loading with COPY and \copy

PostgreSQL offers two mechanisms for bulk data transfer.

Server-side COPY runs with the permissions of the PostgreSQL server process. It reads from (or writes to) a file path that the server can see on its own filesystem. Because the server process owns the operation, you must have superuser or the `pg_read_server_files` role to use it.

```sql

COPY orders (order_id, customer_id, order_date, total)

FROM '/data/orders.csv'

WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', ENCODING 'UTF8');

```

Client-side \copy (note the backslash) is a `psql` meta-command. It streams the file from the client machine through the connection, so no special server privileges are needed. The syntax is nearly identical:

```sql

\copy orders (order_id, customer_id, order_date, total)

FROM 'orders.csv'

WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',');

```

Use `\copy` in classroom and most professional environments where you do not control the server filesystem.

Common import problems and fixes

| Problem | Symptom | Fix |

|---|---|---|

| Wrong delimiter | "extra columns" error | Set `DELIMITER '|'` or `DELIMITER E'\t'` for tabs |

| Date format mismatch | invalid input syntax for type date | Run `SET datestyle = 'ISO, MDY';` before the COPY, or cast in a staging table |

| Non-UTF-8 encoding | invalid byte sequence | Add `ENCODING 'LATIN1'` or recode the file with `iconv` |

| Header row present | first row inserted as data | Add `HEADER TRUE` to the options |

Always document each error message exactly as PostgreSQL returns it and the SQL statement you used to fix it. That log is part of your deliverable today.

---

Integrity Constraints

Constraints are rules attached to a table that PostgreSQL enforces automatically on every `INSERT`, `UPDATE`, and `COPY`. They are your first line of defense against dirty data.

NOT NULL — guarantees a column always has a value. Use it for any column that is required by business rules.

```sql

ALTER TABLE customers ADD CONSTRAINT customers_email_nn NOT NULL (email);

-- Or at table creation:

created_at TIMESTAMP NOT NULL DEFAULT NOW()

```

UNIQUE — guarantees no two rows share the same value in the specified column or column combination.

```sql

ALTER TABLE customers ADD CONSTRAINT customers_email_unique UNIQUE (email);

```

CHECK — evaluates a Boolean expression; the row is rejected if the expression is false. Use it for domain validation such as price ranges or status codes.

```sql

ALTER TABLE products ADD CONSTRAINT products_price_positive CHECK (price > 0);

```

PRIMARY KEY — combines NOT NULL and UNIQUE; every table should have one.

FOREIGN KEY — links a column in one table to the primary key of another, preventing orphaned records.

```sql

ALTER TABLE orders

ADD CONSTRAINT orders_customer_fk

FOREIGN KEY (customer_id) REFERENCES customers (customer_id)

ON DELETE RESTRICT;

```

When you attempt to insert a row that violates any constraint, PostgreSQL returns an error with the constraint name in the message. Record this name and explain the data quality problem the constraint prevents.

---

Exporting Data

Export to CSV — mirror of the import syntax:

```sql

COPY (

SELECT order_id, order_date, total

FROM orders

WHERE total > 100

) TO '/tmp/large_orders.csv'

WITH (FORMAT CSV, HEADER TRUE);

```

Or with `\copy` from psql:

```sql

\copy (SELECT order_id, order_date, total FROM orders WHERE total > 100)

TO 'large_orders.csv' WITH (FORMAT CSV, HEADER TRUE);

```

Export to JSON — PostgreSQL's `json_agg` aggregates rows into a JSON array:

```sql

COPY (

SELECT json_agg(t)

FROM (

SELECT order_id, order_date, total

FROM orders

WHERE total > 100

) t

) TO '/tmp/large_orders.json';

```

Verify the output in Python:

```python

import pandas as pd, json

with open('large_orders.json') as f:

data = json.load(f)

df = pd.DataFrame(data)

print(df.head())

```

---

Safety and Professional Practices

Key terms9

COPY (server-side)A PostgreSQL SQL command that reads from or writes to a file on the database server's filesystem; requires elevated database privileges.
\copy (client-side)A psql meta-command that streams data between the client machine and the database, requiring no special server privileges.
NOT NULL constraintA column-level rule that rejects any INSERT or UPDATE that would leave the column without a value.
UNIQUE constraintA table or column rule that prevents two rows from sharing the same value (or combination of values) in the specified columns.
CHECK constraintA rule that evaluates a Boolean expression on each row; the row is rejected when the expression evaluates to false.
FOREIGN KEY constraintA referential integrity rule that requires every value in a column to match an existing value in a referenced table's primary key, preventing orphaned rows.
json_aggA PostgreSQL aggregate function that collects rows from a query into a single JSON array value.
Staging tableA temporary or intermediate table used to receive raw imported data before it is validated and moved to a permanent table.
ENCODING optionA COPY option that specifies the character encoding of the source or destination file, such as UTF8 or LATIN1, to prevent byte-sequence errors during import.
In class: Bulk load exercise: students use \\copy and the server-side COPY command to load three CSV files with different delimiters, date formats, and encoding issues; they document each error encountered and the SQL fix applied in their lab log. · Constraint stress test: students add five constraints to an existing table, then attempt to insert intentionally invalid rows; they record which constraint blocked each bad row and explain what data quality problem each constraint prevents. · Export pipeline: students export a filtered query result to CSV, then to a JSON array using PostgreSQL's json_agg function, and confirm the file can be opened in Python pandas with no import errors.
Materials: Three messy CSV files (instructor-prepared from public datasets), PostgreSQL COPY documentation, Python 3 with pandas installed, student lab notebooks
Check: Lab log reviewed by instructor: must contain at least three documented import errors with correct fixes, all five constraint tests recorded with correct explanations, and evidence that both export files loaded successfully in pandas; 80% of checklist items complete to pass.

Practice check8

Answer each question, then check it. Nothing is recorded; this is your own practice.

Data ingestion and database operations
1. A student runs \copy and the server-side COPY command to load the same file. Which statement correctly describes the difference between the two?
Data ingestion and database operations
2. During a bulk import, PostgreSQL returns the error: 'invalid byte sequence for encoding UTF8.' What is the most direct fix?
Data quality and integrity
3. A data analyst wants to ensure that no two customers in a table can share the same email address, but the email column may not be the primary key. Which constraint should be applied?
Data quality and integrity
4. Which PostgreSQL constraint would prevent a row from being inserted into an 'order_items' table when the referenced 'order_id' does not exist in the 'orders' table?
Data quality and integrity
5. A student adds a CHECK constraint CHECK (price > 0) to a products table and then attempts to insert a row with price = -5. What will PostgreSQL do?
Data export and transformation
6. To export a filtered query result as a JSON array from PostgreSQL, which function should be used inside a SELECT statement?
Database safety and operations
7. Before altering constraints on a large populated table in a production-like environment, what should a student do first?
Data export and transformation
8. After exporting a query result to a JSON file using json_agg in PostgreSQL, a student wants to verify the file loads correctly. Which Python approach is most appropriate?
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.