2026-09-30 15:59:45
This commit is contained in:
1 parent
d1dc3376bd
commit
4f6a34cfcc
4 files changed
+1216
No files matched your search
@@ -0,0 +1,112 @@
|
||||
# Oracle E-commerce and Accounting Workload
|
||||
|
||||
This project contains three SQL*Plus/SQLcl scripts for creating and exercising
|
||||
an Oracle e-commerce and accounting schema.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Oracle Database 12c or later. The schema uses identity columns and daily
|
||||
interval partitioning.
|
||||
- Run the scripts while connected as the schema owner.
|
||||
- The activity procedure uses `DBMS_LOCK.SLEEP`. The schema owner may need a
|
||||
direct grant from a DBA:
|
||||
|
||||
```sql
|
||||
GRANT EXECUTE ON SYS.DBMS_LOCK TO your_schema;
|
||||
```
|
||||
|
||||
A role grant may not be sufficient when compiling a stored procedure.
|
||||
|
||||
## Scripts and execution order
|
||||
|
||||
Run these scripts in order from SQL*Plus or SQLcl:
|
||||
|
||||
```sql
|
||||
@oracle_ecommerce_schema.sql
|
||||
@oracle_ecommerce_seed_2gb.sql
|
||||
@oracle_ecommerce_activity.sql
|
||||
```
|
||||
|
||||
The schema script creates objects only. The seed script expects the schema to
|
||||
be empty and should be run once. The activity script creates or replaces the
|
||||
workload procedure and can be rerun to install procedure changes.
|
||||
|
||||
## `oracle_ecommerce_schema.sql`
|
||||
|
||||
Creates 22 tables with primary keys, foreign keys, unique and check
|
||||
constraints, and supporting indexes. Seven event/transaction tables use
|
||||
one-day interval range partitioning; Oracle creates daily interval partitions
|
||||
automatically for inserted dates after the initial partition boundary.
|
||||
|
||||
The model covers:
|
||||
|
||||
- **Reference and customer data:** `CURRENCIES`, `SALES_CHANNELS`,
|
||||
`CUSTOMERS`, `CUSTOMER_ADDRESSES`, `SUPPLIERS`, `PRODUCT_CATEGORIES`,
|
||||
`WAREHOUSES`, and `GL_ACCOUNTS`.
|
||||
- **Catalog and inventory:** `PRODUCTS`, `INVENTORY_BALANCES`, and
|
||||
`INVENTORY_MOVEMENTS`.
|
||||
- **Sales and fulfillment:** `SALES_ORDERS`, `SALES_ORDER_LINES`, `PAYMENTS`,
|
||||
`SHIPMENTS`, `SHIPMENT_ITEMS`, and `RETURNS`.
|
||||
- **Purchasing and accounting:** `PURCHASE_ORDERS`, `PURCHASE_ORDER_LINES`,
|
||||
`JOURNAL_ENTRIES`, and `JOURNAL_LINES`.
|
||||
- **Operational history:** `AUDIT_EVENTS`.
|
||||
|
||||
Daily interval-partitioned tables are `SALES_ORDERS`, `PAYMENTS`, `SHIPMENTS`,
|
||||
`INVENTORY_MOVEMENTS`, `JOURNAL_ENTRIES`, `RETURNS`, and `AUDIT_EVENTS`.
|
||||
|
||||
## `oracle_ecommerce_seed_2gb.sql`
|
||||
|
||||
Loads reference and transactional sample data, followed by an audit-event
|
||||
payload of 2 GiB (2,147,483,648 ASCII characters/bytes in the `DETAILS`
|
||||
column). Oracle table, index, and segment overhead makes the allocated
|
||||
database storage larger than 2 GiB. The script generates 1,073,742 audit
|
||||
rows and commits them in batches; the final row contains the remaining
|
||||
payload bytes.
|
||||
|
||||
This is a large load and can consume substantial database time, redo, and
|
||||
storage. It is intended for a test database with enough available space, not
|
||||
for a production data environment. To change its payload size, edit
|
||||
`c_target_payload_bytes` in the script. The number of characters per audit
|
||||
row is controlled by `c_payload_chars` and must remain within the
|
||||
`AUDIT_EVENTS.DETAILS` column capacity.
|
||||
|
||||
## `oracle_ecommerce_activity.sql`
|
||||
|
||||
Creates `SIMULATE_COMMERCE_ACTIVITY`, which randomly performs single-row
|
||||
INSERT, UPDATE, and DELETE operations across these 16 tables:
|
||||
|
||||
`RETURNS`, `PURCHASE_ORDERS`, `PURCHASE_ORDER_LINES`, `PRODUCTS`,
|
||||
`CUSTOMER_ADDRESSES`, `SHIPMENTS`, `PAYMENTS`, `CUSTOMERS`,
|
||||
`JOURNAL_ENTRIES`, `SALES_ORDERS`, `INVENTORY_MOVEMENTS`, `SHIPMENT_ITEMS`,
|
||||
`SALES_ORDER_LINES`, `JOURNAL_LINES`, `INVENTORY_BALANCES`, and `AUDIT_EVENTS`.
|
||||
|
||||
The procedure selects parent keys from existing rows for inserts and limits
|
||||
parent-row deletes to records with no dependent rows. Each successful DML
|
||||
operation affects one row. Updates change representative values/statuses;
|
||||
inserts use synthetic data. Operations commit after each iteration, making
|
||||
changes visible to other sessions, but also committing any uncommitted work
|
||||
already present in the caller's session.
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Meaning |
|
||||
| --- | --- |
|
||||
| `p_iterations` | Number of workload iterations; must be non-negative. |
|
||||
| `p_seconds_between_iterations` | Delay between iterations in seconds; must be non-negative. |
|
||||
| `p_average_rows_per_iteration` | Target average successful DML rows per iteration; must be between 0 and 10,000. Fractional values are randomly rounded across iterations. |
|
||||
|
||||
An iteration may affect fewer rows than its target if it cannot find an eligible
|
||||
row or exhausts its bounded number of attempts. The average is therefore a
|
||||
best-effort target, not a guarantee.
|
||||
|
||||
Example: run 100 iterations, wait 2 seconds between them, and target an average
|
||||
of 5.5 successful row operations per iteration:
|
||||
|
||||
```sql
|
||||
SET SERVEROUTPUT ON
|
||||
EXEC simulate_commerce_activity(100, 2, 5.5);
|
||||
```
|
||||
|
||||
The procedure prints a one-line summary for each iteration and a final total
|
||||
and realized average. `DBMS_OUTPUT` is buffered, so SQL*Plus/SQLcl may display
|
||||
the output after the procedure completes.
|
||||
@@ -0,0 +1,431 @@
|
||||
-- Creates a workload procedure for the e-commerce schema.
|
||||
-- Run as the schema owner after oracle_ecommerce_schema.sql. The workload
|
||||
-- commits after each iteration so other sessions can observe the activity.
|
||||
-- DBMS_LOCK.SLEEP may require EXECUTE on SYS.DBMS_LOCK for the schema owner.
|
||||
-- The average is realized by randomly rounding its fractional part per iteration;
|
||||
-- each successful insert, update, or delete affects one row. Example:
|
||||
-- EXEC simulate_commerce_activity(100, 2, 5.5);
|
||||
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET DEFINE OFF
|
||||
|
||||
CREATE OR REPLACE PROCEDURE simulate_commerce_activity (
|
||||
p_iterations IN PLS_INTEGER,
|
||||
p_seconds_between_iterations IN NUMBER,
|
||||
p_average_rows_per_iteration IN NUMBER
|
||||
) AS
|
||||
TYPE t_varchar_array IS TABLE OF VARCHAR2(1000) INDEX BY PLS_INTEGER;
|
||||
l_tables t_varchar_array;
|
||||
l_update_sets t_varchar_array;
|
||||
l_delete_tests t_varchar_array;
|
||||
l_table_index PLS_INTEGER;
|
||||
l_action PLS_INTEGER;
|
||||
l_target_rows PLS_INTEGER;
|
||||
l_rows_done PLS_INTEGER;
|
||||
l_rows_total NUMBER := 0;
|
||||
l_rows_this PLS_INTEGER;
|
||||
l_attempts PLS_INTEGER;
|
||||
l_rowid UROWID;
|
||||
l_id1 NUMBER;
|
||||
l_id2 NUMBER;
|
||||
l_id3 NUMBER;
|
||||
l_id4 NUMBER;
|
||||
l_id5 NUMBER;
|
||||
l_line_number NUMBER;
|
||||
l_amount NUMBER(14,2);
|
||||
|
||||
FUNCTION random_number(p_table IN VARCHAR2, p_column IN VARCHAR2)
|
||||
RETURN NUMBER
|
||||
IS
|
||||
l_result NUMBER;
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT chosen_value FROM (' ||
|
||||
' SELECT ' || p_column || ' AS chosen_value FROM ' || p_table ||
|
||||
' ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM = 1'
|
||||
INTO l_result;
|
||||
RETURN l_result;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RETURN NULL;
|
||||
END random_number;
|
||||
|
||||
FUNCTION random_rowid(p_table IN VARCHAR2, p_filter IN VARCHAR2)
|
||||
RETURN UROWID
|
||||
IS
|
||||
l_result UROWID;
|
||||
l_sql VARCHAR2(2000);
|
||||
BEGIN
|
||||
l_sql :=
|
||||
'SELECT chosen_rowid FROM (' ||
|
||||
' SELECT ROWID AS chosen_rowid FROM ' || p_table ||
|
||||
' WHERE ' || NVL(p_filter, '1 = 1') ||
|
||||
' ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM = 1';
|
||||
EXECUTE IMMEDIATE l_sql INTO l_result;
|
||||
RETURN l_result;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RETURN NULL;
|
||||
END random_rowid;
|
||||
|
||||
PROCEDURE do_one_activity (
|
||||
p_table_index IN PLS_INTEGER,
|
||||
p_action IN PLS_INTEGER,
|
||||
p_row_count OUT PLS_INTEGER
|
||||
) IS
|
||||
BEGIN
|
||||
p_row_count := 0;
|
||||
l_id1 := NULL;
|
||||
l_id2 := NULL;
|
||||
l_id3 := NULL;
|
||||
l_id4 := NULL;
|
||||
l_id5 := NULL;
|
||||
|
||||
IF p_action = 1 THEN
|
||||
CASE p_table_index
|
||||
WHEN 1 THEN
|
||||
l_id1 := random_number('sales_order_lines', 'order_line_id');
|
||||
l_id2 := random_number('customers', 'customer_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO returns (
|
||||
returned_at, order_line_id, customer_id, return_status,
|
||||
quantity, reason_code
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, 'REQUESTED', 1, 'SIMULATED'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 2 THEN
|
||||
l_id1 := random_number('suppliers', 'supplier_id');
|
||||
l_id2 := random_number('warehouses', 'warehouse_id');
|
||||
l_id3 := random_number('currencies', 'currency_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL AND l_id3 IS NOT NULL THEN
|
||||
INSERT INTO purchase_orders (
|
||||
ordered_at, supplier_id, warehouse_id, currency_id, purchase_status
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, l_id3, 'DRAFT'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 3 THEN
|
||||
l_id1 := random_number('purchase_orders', 'purchase_order_id');
|
||||
l_id2 := random_number('products', 'product_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
SELECT NVL(MAX(line_number), 0) + 1
|
||||
INTO l_line_number
|
||||
FROM purchase_order_lines
|
||||
WHERE purchase_order_id = l_id1;
|
||||
IF l_line_number <= 9999 THEN
|
||||
INSERT INTO purchase_order_lines (
|
||||
purchase_order_id, product_id, line_number, quantity, unit_cost
|
||||
) VALUES (
|
||||
l_id1, l_id2, l_line_number, 1, ROUND(DBMS_RANDOM.VALUE(1, 300), 2)
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
END IF;
|
||||
WHEN 4 THEN
|
||||
l_id1 := random_number('product_categories', 'category_id');
|
||||
l_id2 := random_number('suppliers', 'supplier_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO products (
|
||||
category_id, supplier_id, sku, product_name, unit_price, product_status
|
||||
) VALUES (
|
||||
l_id1, l_id2, 'SIM-' || RAWTOHEX(SYS_GUID()),
|
||||
'Simulated product', ROUND(DBMS_RANDOM.VALUE(1, 500), 2), 'ACTIVE'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 5 THEN
|
||||
l_id1 := random_number('customers', 'customer_id');
|
||||
IF l_id1 IS NOT NULL THEN
|
||||
INSERT INTO customer_addresses (
|
||||
customer_id, address_type, address_line1, city, country_code, is_default
|
||||
) VALUES (
|
||||
l_id1, 'BOTH', '1 Simulation Way', 'Simulated City', 'US', 'N'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 6 THEN
|
||||
l_id1 := random_number('sales_orders', 'order_id');
|
||||
l_id2 := random_number('warehouses', 'warehouse_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO shipments (
|
||||
shipped_at, order_id, warehouse_id, tracking_number,
|
||||
carrier_name, shipment_status
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, 'SIM-' || RAWTOHEX(SYS_GUID()),
|
||||
'Simulation Carrier', 'CREATED'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 7 THEN
|
||||
l_id1 := random_number('sales_orders', 'order_id');
|
||||
l_id2 := random_number('currencies', 'currency_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO payments (
|
||||
payment_date, order_id, currency_id, payment_method,
|
||||
payment_status, amount, provider_reference
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, 'CARD', 'AUTHORIZED',
|
||||
ROUND(DBMS_RANDOM.VALUE(1, 1000), 2), 'SIM-' || RAWTOHEX(SYS_GUID())
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 8 THEN
|
||||
INSERT INTO customers (
|
||||
email, first_name, last_name, customer_since, customer_status
|
||||
) VALUES (
|
||||
'sim-' || RAWTOHEX(SYS_GUID()) || '@example.test',
|
||||
'Simulated', 'Customer', SYSDATE, 'ACTIVE'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
WHEN 9 THEN
|
||||
l_id1 := random_number('currencies', 'currency_id');
|
||||
IF l_id1 IS NOT NULL THEN
|
||||
INSERT INTO journal_entries (
|
||||
posted_at, currency_id, source_type, source_id, entry_status, memo
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, 'SIMULATION', NULL, 'DRAFT', 'Simulated journal entry'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 10 THEN
|
||||
l_id1 := random_number('customers', 'customer_id');
|
||||
l_id2 := random_number('sales_channels', 'channel_id');
|
||||
l_id3 := random_number('currencies', 'currency_id');
|
||||
l_id4 := random_number('customer_addresses', 'address_id');
|
||||
l_id5 := random_number('customer_addresses', 'address_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL AND l_id3 IS NOT NULL
|
||||
AND l_id4 IS NOT NULL AND l_id5 IS NOT NULL THEN
|
||||
INSERT INTO sales_orders (
|
||||
order_date, customer_id, channel_id, currency_id,
|
||||
billing_address_id, shipping_address_id, order_status,
|
||||
subtotal, tax_amount, shipping_amount
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, l_id3, l_id4, l_id5,
|
||||
'PENDING', 0, 0, 0
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 11 THEN
|
||||
l_id1 := random_number('products', 'product_id');
|
||||
l_id2 := random_number('warehouses', 'warehouse_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO inventory_movements (
|
||||
movement_at, product_id, warehouse_id, movement_type,
|
||||
quantity_delta, reference_note
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, l_id2, 'RECEIPT', 1, 'Simulated stock receipt'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 12 THEN
|
||||
l_id1 := random_number('shipments', 'shipment_id');
|
||||
l_id2 := random_number('sales_order_lines', 'order_line_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
INSERT INTO shipment_items (shipment_id, order_line_id, quantity)
|
||||
VALUES (l_id1, l_id2, 1);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
WHEN 13 THEN
|
||||
l_id1 := random_number('sales_orders', 'order_id');
|
||||
l_id2 := random_number('products', 'product_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
SELECT NVL(MAX(line_number), 0) + 1
|
||||
INTO l_line_number
|
||||
FROM sales_order_lines
|
||||
WHERE order_id = l_id1;
|
||||
IF l_line_number <= 9999 THEN
|
||||
INSERT INTO sales_order_lines (
|
||||
order_id, product_id, line_number, quantity,
|
||||
unit_price, discount_amount
|
||||
) VALUES (
|
||||
l_id1, l_id2, l_line_number, 1,
|
||||
ROUND(DBMS_RANDOM.VALUE(1, 500), 2), 0
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
END IF;
|
||||
WHEN 14 THEN
|
||||
l_id1 := random_number('journal_entries', 'journal_entry_id');
|
||||
l_id2 := random_number('gl_accounts', 'account_id');
|
||||
IF l_id1 IS NOT NULL AND l_id2 IS NOT NULL THEN
|
||||
SELECT NVL(MAX(line_number), 0) + 1
|
||||
INTO l_line_number
|
||||
FROM journal_lines
|
||||
WHERE journal_entry_id = l_id1;
|
||||
IF l_line_number <= 9999 THEN
|
||||
l_amount := ROUND(DBMS_RANDOM.VALUE(1, 1000), 2);
|
||||
INSERT INTO journal_lines (
|
||||
journal_entry_id, account_id, line_number,
|
||||
debit_amount, credit_amount, line_memo
|
||||
) VALUES (
|
||||
l_id1, l_id2, l_line_number, l_amount, 0, 'Simulated debit'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
END IF;
|
||||
WHEN 15 THEN
|
||||
BEGIN
|
||||
SELECT product_id, warehouse_id
|
||||
INTO l_id1, l_id2
|
||||
FROM (
|
||||
SELECT p.product_id, w.warehouse_id
|
||||
FROM products p
|
||||
CROSS JOIN warehouses w
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM inventory_balances b
|
||||
WHERE b.product_id = p.product_id
|
||||
AND b.warehouse_id = w.warehouse_id
|
||||
)
|
||||
ORDER BY DBMS_RANDOM.VALUE
|
||||
)
|
||||
WHERE ROWNUM = 1;
|
||||
INSERT INTO inventory_balances (
|
||||
product_id, warehouse_id, quantity_on_hand,
|
||||
quantity_reserved, last_counted_at
|
||||
) VALUES (
|
||||
l_id1, l_id2, 1, 0, SYSDATE
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
NULL;
|
||||
END;
|
||||
WHEN 16 THEN
|
||||
l_id1 := random_number('customers', 'customer_id');
|
||||
INSERT INTO audit_events (
|
||||
event_at, actor_customer_id, event_type, source_ip, details
|
||||
) VALUES (
|
||||
SYSDATE, l_id1, 'SIMULATED_ACTIVITY', '192.0.2.1',
|
||||
'Generated by SIMULATE_COMMERCE_ACTIVITY'
|
||||
);
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END CASE;
|
||||
ELSIF p_action = 2 THEN
|
||||
l_rowid := random_rowid(l_tables(p_table_index), NULL);
|
||||
IF l_rowid IS NOT NULL THEN
|
||||
EXECUTE IMMEDIATE
|
||||
'UPDATE ' || l_tables(p_table_index) ||
|
||||
' SET ' || l_update_sets(p_table_index) ||
|
||||
' WHERE ROWID = :selected_rowid'
|
||||
USING l_rowid;
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
ELSE
|
||||
l_rowid := random_rowid(
|
||||
l_tables(p_table_index), l_delete_tests(p_table_index)
|
||||
);
|
||||
IF l_rowid IS NOT NULL THEN
|
||||
EXECUTE IMMEDIATE
|
||||
'DELETE FROM ' || l_tables(p_table_index) ||
|
||||
' WHERE ROWID = :selected_rowid'
|
||||
USING l_rowid;
|
||||
p_row_count := SQL%ROWCOUNT;
|
||||
END IF;
|
||||
END IF;
|
||||
END do_one_activity;
|
||||
BEGIN
|
||||
IF p_iterations IS NULL OR p_iterations < 0 THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'p_iterations must be a non-negative integer');
|
||||
END IF;
|
||||
IF p_seconds_between_iterations IS NULL OR p_seconds_between_iterations < 0 THEN
|
||||
RAISE_APPLICATION_ERROR(-20002, 'p_seconds_between_iterations must be non-negative');
|
||||
END IF;
|
||||
IF p_average_rows_per_iteration IS NULL OR p_average_rows_per_iteration < 0
|
||||
OR p_average_rows_per_iteration > 10000 THEN
|
||||
RAISE_APPLICATION_ERROR(-20003, 'p_average_rows_per_iteration must be between 0 and 10000');
|
||||
END IF;
|
||||
|
||||
l_tables(1) := 'RETURNS';
|
||||
l_tables(2) := 'PURCHASE_ORDERS';
|
||||
l_tables(3) := 'PURCHASE_ORDER_LINES';
|
||||
l_tables(4) := 'PRODUCTS';
|
||||
l_tables(5) := 'CUSTOMER_ADDRESSES';
|
||||
l_tables(6) := 'SHIPMENTS';
|
||||
l_tables(7) := 'PAYMENTS';
|
||||
l_tables(8) := 'CUSTOMERS';
|
||||
l_tables(9) := 'JOURNAL_ENTRIES';
|
||||
l_tables(10) := 'SALES_ORDERS';
|
||||
l_tables(11) := 'INVENTORY_MOVEMENTS';
|
||||
l_tables(12) := 'SHIPMENT_ITEMS';
|
||||
l_tables(13) := 'SALES_ORDER_LINES';
|
||||
l_tables(14) := 'JOURNAL_LINES';
|
||||
l_tables(15) := 'INVENTORY_BALANCES';
|
||||
l_tables(16) := 'AUDIT_EVENTS';
|
||||
|
||||
l_update_sets(1) := 'return_status = CASE return_status WHEN ''REQUESTED'' THEN ''APPROVED'' ELSE ''REQUESTED'' END';
|
||||
l_update_sets(2) := 'purchase_status = CASE purchase_status WHEN ''DRAFT'' THEN ''ORDERED'' WHEN ''ORDERED'' THEN ''RECEIVED'' ELSE ''DRAFT'' END';
|
||||
l_update_sets(3) := 'quantity = quantity + 1';
|
||||
l_update_sets(4) := 'unit_price = unit_price + 1, product_status = CASE product_status WHEN ''ACTIVE'' THEN ''DISCONTINUED'' ELSE ''ACTIVE'' END';
|
||||
l_update_sets(5) := 'city = SUBSTR(city || ''X'', 1, 80)';
|
||||
l_update_sets(6) := 'shipment_status = CASE shipment_status WHEN ''CREATED'' THEN ''IN_TRANSIT'' WHEN ''IN_TRANSIT'' THEN ''DELIVERED'' ELSE ''CREATED'' END';
|
||||
l_update_sets(7) := 'payment_status = CASE payment_status WHEN ''AUTHORIZED'' THEN ''CAPTURED'' WHEN ''CAPTURED'' THEN ''REFUNDED'' ELSE ''AUTHORIZED'' END';
|
||||
l_update_sets(8) := 'phone_number = ''SIM-'' || TO_CHAR(TRUNC(DBMS_RANDOM.VALUE(100000, 999999))), customer_status = CASE customer_status WHEN ''ACTIVE'' THEN ''INACTIVE'' ELSE ''ACTIVE'' END';
|
||||
l_update_sets(9) := 'entry_status = CASE entry_status WHEN ''DRAFT'' THEN ''POSTED'' WHEN ''POSTED'' THEN ''VOID'' ELSE ''DRAFT'' END, memo = SUBSTR(memo || '' *'', 1, 240)';
|
||||
l_update_sets(10) := 'order_status = CASE order_status WHEN ''PENDING'' THEN ''PAID'' WHEN ''PAID'' THEN ''FULFILLED'' ELSE ''PENDING'' END, subtotal = subtotal + 1';
|
||||
l_update_sets(11) := 'quantity_delta = -quantity_delta, reference_note = ''Simulated movement update''';
|
||||
l_update_sets(12) := 'quantity = quantity + 1';
|
||||
l_update_sets(13) := 'quantity = quantity + 1';
|
||||
l_update_sets(14) := 'debit_amount = CASE WHEN debit_amount > 0 THEN debit_amount + 1 ELSE 0 END, credit_amount = CASE WHEN credit_amount > 0 THEN credit_amount + 1 ELSE 0 END';
|
||||
l_update_sets(15) := 'quantity_on_hand = quantity_on_hand + 1, last_counted_at = SYSDATE';
|
||||
l_update_sets(16) := 'details = SUBSTR(details || ''x'', 1, 2000)';
|
||||
|
||||
l_delete_tests(1) := '1 = 1';
|
||||
l_delete_tests(2) := 'NOT EXISTS (SELECT 1 FROM purchase_order_lines x WHERE x.purchase_order_id = purchase_orders.purchase_order_id)';
|
||||
l_delete_tests(3) := '1 = 1';
|
||||
l_delete_tests(4) := 'NOT EXISTS (SELECT 1 FROM sales_order_lines x WHERE x.product_id = products.product_id) AND NOT EXISTS (SELECT 1 FROM inventory_balances x WHERE x.product_id = products.product_id) AND NOT EXISTS (SELECT 1 FROM inventory_movements x WHERE x.product_id = products.product_id) AND NOT EXISTS (SELECT 1 FROM purchase_order_lines x WHERE x.product_id = products.product_id)';
|
||||
l_delete_tests(5) := 'NOT EXISTS (SELECT 1 FROM sales_orders x WHERE x.billing_address_id = customer_addresses.address_id OR x.shipping_address_id = customer_addresses.address_id)';
|
||||
l_delete_tests(6) := 'NOT EXISTS (SELECT 1 FROM shipment_items x WHERE x.shipment_id = shipments.shipment_id)';
|
||||
l_delete_tests(7) := '1 = 1';
|
||||
l_delete_tests(8) := 'NOT EXISTS (SELECT 1 FROM customer_addresses x WHERE x.customer_id = customers.customer_id) AND NOT EXISTS (SELECT 1 FROM sales_orders x WHERE x.customer_id = customers.customer_id) AND NOT EXISTS (SELECT 1 FROM returns x WHERE x.customer_id = customers.customer_id) AND NOT EXISTS (SELECT 1 FROM audit_events x WHERE x.actor_customer_id = customers.customer_id)';
|
||||
l_delete_tests(9) := 'NOT EXISTS (SELECT 1 FROM journal_lines x WHERE x.journal_entry_id = journal_entries.journal_entry_id)';
|
||||
l_delete_tests(10) := 'NOT EXISTS (SELECT 1 FROM sales_order_lines x WHERE x.order_id = sales_orders.order_id) AND NOT EXISTS (SELECT 1 FROM payments x WHERE x.order_id = sales_orders.order_id) AND NOT EXISTS (SELECT 1 FROM shipments x WHERE x.order_id = sales_orders.order_id)';
|
||||
l_delete_tests(11) := '1 = 1';
|
||||
l_delete_tests(12) := '1 = 1';
|
||||
l_delete_tests(13) := 'NOT EXISTS (SELECT 1 FROM shipment_items x WHERE x.order_line_id = sales_order_lines.order_line_id) AND NOT EXISTS (SELECT 1 FROM inventory_movements x WHERE x.order_line_id = sales_order_lines.order_line_id) AND NOT EXISTS (SELECT 1 FROM returns x WHERE x.order_line_id = sales_order_lines.order_line_id)';
|
||||
l_delete_tests(14) := '1 = 1';
|
||||
l_delete_tests(15) := '1 = 1';
|
||||
l_delete_tests(16) := '1 = 1';
|
||||
|
||||
FOR iteration_no IN 1 .. p_iterations LOOP
|
||||
l_target_rows := TRUNC(p_average_rows_per_iteration);
|
||||
IF DBMS_RANDOM.VALUE(0, 1) <
|
||||
p_average_rows_per_iteration - TRUNC(p_average_rows_per_iteration) THEN
|
||||
l_target_rows := l_target_rows + 1;
|
||||
END IF;
|
||||
|
||||
l_rows_done := 0;
|
||||
l_attempts := 0;
|
||||
WHILE l_rows_done < l_target_rows AND l_attempts < (l_target_rows * 20 + 100) LOOP
|
||||
l_table_index := TRUNC(DBMS_RANDOM.VALUE(1, 17));
|
||||
l_action := TRUNC(DBMS_RANDOM.VALUE(1, 4));
|
||||
do_one_activity(l_table_index, l_action, l_rows_this);
|
||||
l_rows_done := l_rows_done + l_rows_this;
|
||||
l_attempts := l_attempts + 1;
|
||||
END LOOP;
|
||||
|
||||
COMMIT;
|
||||
l_rows_total := l_rows_total + l_rows_done;
|
||||
DBMS_OUTPUT.PUT_LINE(
|
||||
'Iteration ' || iteration_no || ': ' || l_rows_done ||
|
||||
' row(s) affected (target ' || l_target_rows || ')'
|
||||
);
|
||||
|
||||
IF iteration_no < p_iterations AND p_seconds_between_iterations > 0 THEN
|
||||
DBMS_LOCK.SLEEP(p_seconds_between_iterations);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
IF p_iterations > 0 THEN
|
||||
DBMS_OUTPUT.PUT_LINE(
|
||||
'Total rows affected: ' || l_rows_total ||
|
||||
'; actual average per iteration: ' || ROUND(l_rows_total / p_iterations, 2)
|
||||
);
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
SHOW ERRORS PROCEDURE simulate_commerce_activity
|
||||
@@ -0,0 +1,364 @@
|
||||
-- Oracle 12c+ schema for an e-commerce and accounting workload.
|
||||
-- Run as the schema owner in SQL*Plus or SQLcl. This script creates objects only.
|
||||
-- The interval-partitioned tables create one-day partitions automatically as dates
|
||||
-- are inserted beyond their initial boundary.
|
||||
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET DEFINE OFF
|
||||
|
||||
CREATE TABLE currencies (
|
||||
currency_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
currency_code CHAR(3) NOT NULL,
|
||||
currency_name VARCHAR2(60) NOT NULL,
|
||||
currency_symbol VARCHAR2(8),
|
||||
CONSTRAINT pk_currencies PRIMARY KEY (currency_id),
|
||||
CONSTRAINT uq_currencies_code UNIQUE (currency_code)
|
||||
);
|
||||
|
||||
CREATE TABLE sales_channels (
|
||||
channel_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
channel_name VARCHAR2(40) NOT NULL,
|
||||
CONSTRAINT pk_sales_channels PRIMARY KEY (channel_id),
|
||||
CONSTRAINT uq_sales_channels_name UNIQUE (channel_name)
|
||||
);
|
||||
|
||||
CREATE TABLE customers (
|
||||
customer_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
email VARCHAR2(254) NOT NULL,
|
||||
first_name VARCHAR2(60) NOT NULL,
|
||||
last_name VARCHAR2(60) NOT NULL,
|
||||
phone_number VARCHAR2(30),
|
||||
customer_since DATE DEFAULT SYSDATE NOT NULL,
|
||||
customer_status VARCHAR2(12) DEFAULT 'ACTIVE' NOT NULL,
|
||||
CONSTRAINT pk_customers PRIMARY KEY (customer_id),
|
||||
CONSTRAINT uq_customers_email UNIQUE (email),
|
||||
CONSTRAINT ck_customers_status CHECK (customer_status IN ('ACTIVE', 'INACTIVE', 'BLOCKED'))
|
||||
);
|
||||
|
||||
CREATE TABLE customer_addresses (
|
||||
address_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
customer_id NUMBER NOT NULL,
|
||||
address_type VARCHAR2(12) NOT NULL,
|
||||
address_line1 VARCHAR2(120) NOT NULL,
|
||||
address_line2 VARCHAR2(120),
|
||||
city VARCHAR2(80) NOT NULL,
|
||||
region VARCHAR2(80),
|
||||
postal_code VARCHAR2(20),
|
||||
country_code CHAR(2) NOT NULL,
|
||||
is_default CHAR(1) DEFAULT 'N' NOT NULL,
|
||||
CONSTRAINT pk_customer_addresses PRIMARY KEY (address_id),
|
||||
CONSTRAINT fk_addresses_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
|
||||
CONSTRAINT ck_addresses_type CHECK (address_type IN ('BILLING', 'SHIPPING', 'BOTH')),
|
||||
CONSTRAINT ck_addresses_default CHECK (is_default IN ('Y', 'N'))
|
||||
);
|
||||
|
||||
CREATE TABLE suppliers (
|
||||
supplier_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
supplier_name VARCHAR2(120) NOT NULL,
|
||||
email VARCHAR2(254),
|
||||
country_code CHAR(2) NOT NULL,
|
||||
supplier_status VARCHAR2(12) DEFAULT 'ACTIVE' NOT NULL,
|
||||
CONSTRAINT pk_suppliers PRIMARY KEY (supplier_id),
|
||||
CONSTRAINT uq_suppliers_name UNIQUE (supplier_name),
|
||||
CONSTRAINT ck_suppliers_status CHECK (supplier_status IN ('ACTIVE', 'INACTIVE'))
|
||||
);
|
||||
|
||||
CREATE TABLE product_categories (
|
||||
category_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
parent_category_id NUMBER,
|
||||
category_name VARCHAR2(100) NOT NULL,
|
||||
CONSTRAINT pk_product_categories PRIMARY KEY (category_id),
|
||||
CONSTRAINT fk_category_parent FOREIGN KEY (parent_category_id) REFERENCES product_categories (category_id),
|
||||
CONSTRAINT uq_category_name UNIQUE (category_name)
|
||||
);
|
||||
|
||||
CREATE TABLE products (
|
||||
product_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
category_id NUMBER NOT NULL,
|
||||
supplier_id NUMBER NOT NULL,
|
||||
sku VARCHAR2(40) NOT NULL,
|
||||
product_name VARCHAR2(160) NOT NULL,
|
||||
unit_price NUMBER(12,2) NOT NULL,
|
||||
product_status VARCHAR2(12) DEFAULT 'ACTIVE' NOT NULL,
|
||||
CONSTRAINT pk_products PRIMARY KEY (product_id),
|
||||
CONSTRAINT uq_products_sku UNIQUE (sku),
|
||||
CONSTRAINT fk_products_category FOREIGN KEY (category_id) REFERENCES product_categories (category_id),
|
||||
CONSTRAINT fk_products_supplier FOREIGN KEY (supplier_id) REFERENCES suppliers (supplier_id),
|
||||
CONSTRAINT ck_products_price CHECK (unit_price >= 0),
|
||||
CONSTRAINT ck_products_status CHECK (product_status IN ('ACTIVE', 'DISCONTINUED'))
|
||||
);
|
||||
|
||||
CREATE TABLE warehouses (
|
||||
warehouse_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
warehouse_name VARCHAR2(100) NOT NULL,
|
||||
country_code CHAR(2) NOT NULL,
|
||||
CONSTRAINT pk_warehouses PRIMARY KEY (warehouse_id),
|
||||
CONSTRAINT uq_warehouses_name UNIQUE (warehouse_name)
|
||||
);
|
||||
|
||||
CREATE TABLE inventory_balances (
|
||||
product_id NUMBER NOT NULL,
|
||||
warehouse_id NUMBER NOT NULL,
|
||||
quantity_on_hand NUMBER(12,2) DEFAULT 0 NOT NULL,
|
||||
quantity_reserved NUMBER(12,2) DEFAULT 0 NOT NULL,
|
||||
last_counted_at DATE,
|
||||
CONSTRAINT pk_inventory_balances PRIMARY KEY (product_id, warehouse_id),
|
||||
CONSTRAINT fk_invbal_product FOREIGN KEY (product_id) REFERENCES products (product_id),
|
||||
CONSTRAINT fk_invbal_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouses (warehouse_id),
|
||||
CONSTRAINT ck_invbal_on_hand CHECK (quantity_on_hand >= 0),
|
||||
CONSTRAINT ck_invbal_reserved CHECK (quantity_reserved >= 0 AND quantity_reserved <= quantity_on_hand)
|
||||
);
|
||||
|
||||
CREATE TABLE sales_orders (
|
||||
order_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
order_date DATE NOT NULL,
|
||||
customer_id NUMBER NOT NULL,
|
||||
channel_id NUMBER NOT NULL,
|
||||
currency_id NUMBER NOT NULL,
|
||||
billing_address_id NUMBER NOT NULL,
|
||||
shipping_address_id NUMBER NOT NULL,
|
||||
order_status VARCHAR2(16) DEFAULT 'PENDING' NOT NULL,
|
||||
subtotal NUMBER(14,2) NOT NULL,
|
||||
tax_amount NUMBER(14,2) DEFAULT 0 NOT NULL,
|
||||
shipping_amount NUMBER(14,2) DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT pk_sales_orders PRIMARY KEY (order_id),
|
||||
CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
|
||||
CONSTRAINT fk_orders_channel FOREIGN KEY (channel_id) REFERENCES sales_channels (channel_id),
|
||||
CONSTRAINT fk_orders_currency FOREIGN KEY (currency_id) REFERENCES currencies (currency_id),
|
||||
CONSTRAINT fk_orders_bill_addr FOREIGN KEY (billing_address_id) REFERENCES customer_addresses (address_id),
|
||||
CONSTRAINT fk_orders_ship_addr FOREIGN KEY (shipping_address_id) REFERENCES customer_addresses (address_id),
|
||||
CONSTRAINT ck_orders_status CHECK (order_status IN ('PENDING', 'PAID', 'FULFILLED', 'CANCELLED', 'REFUNDED')),
|
||||
CONSTRAINT ck_orders_amounts CHECK (subtotal >= 0 AND tax_amount >= 0 AND shipping_amount >= 0)
|
||||
)
|
||||
PARTITION BY RANGE (order_date)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_orders_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE sales_order_lines (
|
||||
order_line_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
order_id NUMBER NOT NULL,
|
||||
product_id NUMBER NOT NULL,
|
||||
line_number NUMBER(4) NOT NULL,
|
||||
quantity NUMBER(12,2) NOT NULL,
|
||||
unit_price NUMBER(12,2) NOT NULL,
|
||||
discount_amount NUMBER(12,2) DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT pk_sales_order_lines PRIMARY KEY (order_line_id),
|
||||
CONSTRAINT fk_lines_order FOREIGN KEY (order_id) REFERENCES sales_orders (order_id),
|
||||
CONSTRAINT fk_lines_product FOREIGN KEY (product_id) REFERENCES products (product_id),
|
||||
CONSTRAINT uq_lines_order_num UNIQUE (order_id, line_number),
|
||||
CONSTRAINT ck_lines_values CHECK (quantity > 0 AND unit_price >= 0 AND discount_amount >= 0)
|
||||
);
|
||||
|
||||
CREATE TABLE payments (
|
||||
payment_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
payment_date DATE NOT NULL,
|
||||
order_id NUMBER NOT NULL,
|
||||
currency_id NUMBER NOT NULL,
|
||||
payment_method VARCHAR2(16) NOT NULL,
|
||||
payment_status VARCHAR2(16) NOT NULL,
|
||||
amount NUMBER(14,2) NOT NULL,
|
||||
provider_reference VARCHAR2(80),
|
||||
CONSTRAINT pk_payments PRIMARY KEY (payment_id),
|
||||
CONSTRAINT fk_payments_order FOREIGN KEY (order_id) REFERENCES sales_orders (order_id),
|
||||
CONSTRAINT fk_payments_currency FOREIGN KEY (currency_id) REFERENCES currencies (currency_id),
|
||||
CONSTRAINT ck_payments_method CHECK (payment_method IN ('CARD', 'BANK', 'WALLET', 'CASH')),
|
||||
CONSTRAINT ck_payments_status CHECK (payment_status IN ('AUTHORIZED', 'CAPTURED', 'FAILED', 'REFUNDED')),
|
||||
CONSTRAINT ck_payments_amount CHECK (amount >= 0)
|
||||
)
|
||||
PARTITION BY RANGE (payment_date)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_payments_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE shipments (
|
||||
shipment_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
shipped_at DATE NOT NULL,
|
||||
order_id NUMBER NOT NULL,
|
||||
warehouse_id NUMBER NOT NULL,
|
||||
tracking_number VARCHAR2(80) NOT NULL,
|
||||
carrier_name VARCHAR2(60) NOT NULL,
|
||||
shipment_status VARCHAR2(16) NOT NULL,
|
||||
CONSTRAINT pk_shipments PRIMARY KEY (shipment_id),
|
||||
CONSTRAINT fk_shipments_order FOREIGN KEY (order_id) REFERENCES sales_orders (order_id),
|
||||
CONSTRAINT fk_shipments_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouses (warehouse_id),
|
||||
CONSTRAINT uq_shipments_tracking UNIQUE (tracking_number),
|
||||
CONSTRAINT ck_shipments_status CHECK (shipment_status IN ('CREATED', 'IN_TRANSIT', 'DELIVERED', 'LOST', 'RETURNED'))
|
||||
)
|
||||
PARTITION BY RANGE (shipped_at)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_shipments_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE shipment_items (
|
||||
shipment_item_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
shipment_id NUMBER NOT NULL,
|
||||
order_line_id NUMBER NOT NULL,
|
||||
quantity NUMBER(12,2) NOT NULL,
|
||||
CONSTRAINT pk_shipment_items PRIMARY KEY (shipment_item_id),
|
||||
CONSTRAINT fk_shipitems_shipment FOREIGN KEY (shipment_id) REFERENCES shipments (shipment_id),
|
||||
CONSTRAINT fk_shipitems_line FOREIGN KEY (order_line_id) REFERENCES sales_order_lines (order_line_id),
|
||||
CONSTRAINT ck_shipitems_qty CHECK (quantity > 0)
|
||||
);
|
||||
|
||||
CREATE TABLE purchase_orders (
|
||||
purchase_order_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
ordered_at DATE NOT NULL,
|
||||
supplier_id NUMBER NOT NULL,
|
||||
warehouse_id NUMBER NOT NULL,
|
||||
currency_id NUMBER NOT NULL,
|
||||
purchase_status VARCHAR2(16) NOT NULL,
|
||||
CONSTRAINT pk_purchase_orders PRIMARY KEY (purchase_order_id),
|
||||
CONSTRAINT fk_po_supplier FOREIGN KEY (supplier_id) REFERENCES suppliers (supplier_id),
|
||||
CONSTRAINT fk_po_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouses (warehouse_id),
|
||||
CONSTRAINT fk_po_currency FOREIGN KEY (currency_id) REFERENCES currencies (currency_id),
|
||||
CONSTRAINT ck_po_status CHECK (purchase_status IN ('DRAFT', 'ORDERED', 'RECEIVED', 'CANCELLED'))
|
||||
);
|
||||
|
||||
CREATE TABLE purchase_order_lines (
|
||||
purchase_line_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
purchase_order_id NUMBER NOT NULL,
|
||||
product_id NUMBER NOT NULL,
|
||||
line_number NUMBER(4) NOT NULL,
|
||||
quantity NUMBER(12,2) NOT NULL,
|
||||
unit_cost NUMBER(12,2) NOT NULL,
|
||||
CONSTRAINT pk_purchase_order_lines PRIMARY KEY (purchase_line_id),
|
||||
CONSTRAINT fk_pol_order FOREIGN KEY (purchase_order_id) REFERENCES purchase_orders (purchase_order_id),
|
||||
CONSTRAINT fk_pol_product FOREIGN KEY (product_id) REFERENCES products (product_id),
|
||||
CONSTRAINT uq_poline_order_num UNIQUE (purchase_order_id, line_number),
|
||||
CONSTRAINT ck_poline_values CHECK (quantity > 0 AND unit_cost >= 0)
|
||||
);
|
||||
|
||||
CREATE TABLE inventory_movements (
|
||||
movement_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
movement_at DATE NOT NULL,
|
||||
product_id NUMBER NOT NULL,
|
||||
warehouse_id NUMBER NOT NULL,
|
||||
order_line_id NUMBER,
|
||||
movement_type VARCHAR2(16) NOT NULL,
|
||||
quantity_delta NUMBER(12,2) NOT NULL,
|
||||
reference_note VARCHAR2(120),
|
||||
CONSTRAINT pk_inventory_movements PRIMARY KEY (movement_id),
|
||||
CONSTRAINT fk_movements_product FOREIGN KEY (product_id) REFERENCES products (product_id),
|
||||
CONSTRAINT fk_movements_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouses (warehouse_id),
|
||||
CONSTRAINT fk_movements_order_line FOREIGN KEY (order_line_id) REFERENCES sales_order_lines (order_line_id),
|
||||
CONSTRAINT ck_movements_type CHECK (movement_type IN ('RECEIPT', 'SALE', 'RETURN', 'ADJUSTMENT')),
|
||||
CONSTRAINT ck_movements_quantity CHECK (quantity_delta <> 0)
|
||||
)
|
||||
PARTITION BY RANGE (movement_at)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_movements_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE gl_accounts (
|
||||
account_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
account_code VARCHAR2(20) NOT NULL,
|
||||
account_name VARCHAR2(100) NOT NULL,
|
||||
account_type VARCHAR2(12) NOT NULL,
|
||||
CONSTRAINT pk_gl_accounts PRIMARY KEY (account_id),
|
||||
CONSTRAINT uq_gl_accounts_code UNIQUE (account_code),
|
||||
CONSTRAINT ck_gl_accounts_type CHECK (account_type IN ('ASSET', 'LIABILITY', 'EQUITY', 'REVENUE', 'EXPENSE'))
|
||||
);
|
||||
|
||||
CREATE TABLE journal_entries (
|
||||
journal_entry_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
posted_at DATE NOT NULL,
|
||||
currency_id NUMBER NOT NULL,
|
||||
source_type VARCHAR2(20) NOT NULL,
|
||||
source_id NUMBER,
|
||||
entry_status VARCHAR2(12) DEFAULT 'POSTED' NOT NULL,
|
||||
memo VARCHAR2(240) NOT NULL,
|
||||
CONSTRAINT pk_journal_entries PRIMARY KEY (journal_entry_id),
|
||||
CONSTRAINT fk_journal_currency FOREIGN KEY (currency_id) REFERENCES currencies (currency_id),
|
||||
CONSTRAINT ck_journal_status CHECK (entry_status IN ('DRAFT', 'POSTED', 'VOID'))
|
||||
)
|
||||
PARTITION BY RANGE (posted_at)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_journal_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE journal_lines (
|
||||
journal_line_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
journal_entry_id NUMBER NOT NULL,
|
||||
account_id NUMBER NOT NULL,
|
||||
line_number NUMBER(4) NOT NULL,
|
||||
debit_amount NUMBER(14,2) DEFAULT 0 NOT NULL,
|
||||
credit_amount NUMBER(14,2) DEFAULT 0 NOT NULL,
|
||||
line_memo VARCHAR2(160),
|
||||
CONSTRAINT pk_journal_lines PRIMARY KEY (journal_line_id),
|
||||
CONSTRAINT fk_jlines_entry FOREIGN KEY (journal_entry_id) REFERENCES journal_entries (journal_entry_id),
|
||||
CONSTRAINT fk_jlines_account FOREIGN KEY (account_id) REFERENCES gl_accounts (account_id),
|
||||
CONSTRAINT uq_jlines_entry_num UNIQUE (journal_entry_id, line_number),
|
||||
CONSTRAINT ck_jlines_amount CHECK (
|
||||
debit_amount >= 0 AND credit_amount >= 0 AND
|
||||
((debit_amount > 0 AND credit_amount = 0) OR
|
||||
(credit_amount > 0 AND debit_amount = 0))
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE returns (
|
||||
return_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
returned_at DATE NOT NULL,
|
||||
order_line_id NUMBER NOT NULL,
|
||||
customer_id NUMBER NOT NULL,
|
||||
return_status VARCHAR2(16) NOT NULL,
|
||||
quantity NUMBER(12,2) NOT NULL,
|
||||
reason_code VARCHAR2(24) NOT NULL,
|
||||
CONSTRAINT pk_returns PRIMARY KEY (return_id),
|
||||
CONSTRAINT fk_returns_line FOREIGN KEY (order_line_id) REFERENCES sales_order_lines (order_line_id),
|
||||
CONSTRAINT fk_returns_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
|
||||
CONSTRAINT ck_returns_status CHECK (return_status IN ('REQUESTED', 'APPROVED', 'RECEIVED', 'REJECTED', 'REFUNDED')),
|
||||
CONSTRAINT ck_returns_quantity CHECK (quantity > 0)
|
||||
)
|
||||
PARTITION BY RANGE (returned_at)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_returns_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE TABLE audit_events (
|
||||
event_id NUMBER GENERATED ALWAYS AS IDENTITY,
|
||||
event_at DATE NOT NULL,
|
||||
actor_customer_id NUMBER,
|
||||
event_type VARCHAR2(30) NOT NULL,
|
||||
source_ip VARCHAR2(45) NOT NULL,
|
||||
details VARCHAR2(2000) NOT NULL,
|
||||
CONSTRAINT pk_audit_events PRIMARY KEY (event_id),
|
||||
CONSTRAINT fk_audit_customer FOREIGN KEY (actor_customer_id) REFERENCES customers (customer_id)
|
||||
)
|
||||
PARTITION BY RANGE (event_at)
|
||||
INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
|
||||
(
|
||||
PARTITION p_audit_seed VALUES LESS THAN (DATE '2025-01-01')
|
||||
);
|
||||
|
||||
CREATE INDEX ix_addresses_customer ON customer_addresses (customer_id);
|
||||
CREATE INDEX ix_products_category ON products (category_id);
|
||||
CREATE INDEX ix_products_supplier ON products (supplier_id);
|
||||
CREATE INDEX ix_invbal_warehouse ON inventory_balances (warehouse_id);
|
||||
CREATE INDEX ix_orders_customer_day ON sales_orders (customer_id, order_date) LOCAL;
|
||||
CREATE INDEX ix_orders_status_day ON sales_orders (order_status, order_date) LOCAL;
|
||||
CREATE INDEX ix_lines_product ON sales_order_lines (product_id);
|
||||
CREATE INDEX ix_payments_order_day ON payments (order_id, payment_date) LOCAL;
|
||||
CREATE INDEX ix_payments_status_day ON payments (payment_status, payment_date) LOCAL;
|
||||
CREATE INDEX ix_shipments_order_day ON shipments (order_id, shipped_at) LOCAL;
|
||||
CREATE INDEX ix_shipments_warehouse ON shipments (warehouse_id);
|
||||
CREATE INDEX ix_shipitems_line ON shipment_items (order_line_id);
|
||||
CREATE INDEX ix_po_supplier ON purchase_orders (supplier_id);
|
||||
CREATE INDEX ix_po_warehouse ON purchase_orders (warehouse_id);
|
||||
CREATE INDEX ix_poline_product ON purchase_order_lines (product_id);
|
||||
CREATE INDEX ix_movements_product_day ON inventory_movements (product_id, movement_at) LOCAL;
|
||||
CREATE INDEX ix_movements_warehouse_day ON inventory_movements (warehouse_id, movement_at) LOCAL;
|
||||
CREATE INDEX ix_journal_source_day ON journal_entries (source_type, posted_at) LOCAL;
|
||||
CREATE INDEX ix_jlines_account ON journal_lines (account_id);
|
||||
CREATE INDEX ix_returns_customer_day ON returns (customer_id, returned_at) LOCAL;
|
||||
CREATE INDEX ix_returns_line ON returns (order_line_id);
|
||||
CREATE INDEX ix_audit_customer_day ON audit_events (actor_customer_id, event_at) LOCAL;
|
||||
CREATE INDEX ix_audit_type_day ON audit_events (event_type, event_at) LOCAL;
|
||||
|
||||
PROMPT Schema created: 22 tables, daily interval partitions, constraints, and indexes.
|
||||
@@ -0,0 +1,309 @@
|
||||
-- Random sample data for oracle_ecommerce_schema.sql.
|
||||
-- Run once, as the same schema owner, after creating the schema in an empty schema.
|
||||
-- The large audit_events load writes exactly 2 GiB of ASCII details payload
|
||||
-- (2,147,483,648 bytes); table/index allocation and other rows add Oracle overhead.
|
||||
-- Adjust c_target_payload_bytes or c_payload_chars below to change the load size.
|
||||
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK
|
||||
SET DEFINE OFF
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
DECLARE
|
||||
l_line_id NUMBER := 0;
|
||||
l_purchase_line_id NUMBER := 0;
|
||||
l_journal_line_id NUMBER := 0;
|
||||
l_journal_amount NUMBER(14,2);
|
||||
l_batch_size PLS_INTEGER := 5000;
|
||||
l_batch_rows PLS_INTEGER;
|
||||
l_offset NUMBER;
|
||||
l_rows NUMBER;
|
||||
c_payload_chars CONSTANT PLS_INTEGER := 2000;
|
||||
c_target_payload_bytes CONSTANT NUMBER := 2147483648;
|
||||
BEGIN
|
||||
DBMS_RANDOM.SEED(20260927);
|
||||
|
||||
INSERT INTO currencies (currency_code, currency_name, currency_symbol)
|
||||
VALUES ('USD', 'US Dollar', '$');
|
||||
INSERT INTO currencies (currency_code, currency_name, currency_symbol)
|
||||
VALUES ('EUR', 'Euro', 'EUR');
|
||||
INSERT INTO currencies (currency_code, currency_name, currency_symbol)
|
||||
VALUES ('GBP', 'Pound Sterling', 'GBP');
|
||||
|
||||
INSERT INTO sales_channels (channel_name) VALUES ('Web Store');
|
||||
INSERT INTO sales_channels (channel_name) VALUES ('Mobile App');
|
||||
INSERT INTO sales_channels (channel_name) VALUES ('Marketplace');
|
||||
INSERT INTO sales_channels (channel_name) VALUES ('Retail POS');
|
||||
|
||||
FOR i IN 1..1000 LOOP
|
||||
INSERT INTO customers (
|
||||
email, first_name, last_name, phone_number, customer_since, customer_status
|
||||
) VALUES (
|
||||
'customer' || TO_CHAR(i) || '@example.test',
|
||||
'First' || TO_CHAR(i),
|
||||
'Last' || TO_CHAR(i),
|
||||
'+1-555-' || TO_CHAR(1000000 + i),
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 2000)),
|
||||
CASE WHEN DBMS_RANDOM.VALUE(0, 1) < 0.97 THEN 'ACTIVE' ELSE 'INACTIVE' END
|
||||
);
|
||||
|
||||
INSERT INTO customer_addresses (
|
||||
customer_id, address_type, address_line1, city, region, postal_code, country_code, is_default
|
||||
) VALUES (
|
||||
i, 'BOTH', TO_CHAR(100 + i) || ' Commerce Street',
|
||||
'City' || TO_CHAR(MOD(i, 100) + 1), 'Region ' || TO_CHAR(MOD(i, 20) + 1),
|
||||
TO_CHAR(10000 + i), 'US', 'Y'
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..50 LOOP
|
||||
INSERT INTO suppliers (supplier_name, email, country_code, supplier_status)
|
||||
VALUES (
|
||||
'Supplier ' || TO_CHAR(i), 'supplier' || TO_CHAR(i) || '@example.test',
|
||||
CASE WHEN MOD(i, 3) = 0 THEN 'GB' WHEN MOD(i, 3) = 1 THEN 'US' ELSE 'DE' END,
|
||||
'ACTIVE'
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..30 LOOP
|
||||
INSERT INTO product_categories (category_name)
|
||||
VALUES ('Category ' || TO_CHAR(i));
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..500 LOOP
|
||||
INSERT INTO products (
|
||||
category_id, supplier_id, sku, product_name, unit_price, product_status
|
||||
) VALUES (
|
||||
MOD(i - 1, 30) + 1, MOD(i - 1, 50) + 1,
|
||||
'SKU-' || LPAD(TO_CHAR(i), 6, '0'),
|
||||
'Catalog Product ' || TO_CHAR(i),
|
||||
ROUND(DBMS_RANDOM.VALUE(5, 500), 2), 'ACTIVE'
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..10 LOOP
|
||||
INSERT INTO warehouses (warehouse_name, country_code)
|
||||
VALUES (
|
||||
'Warehouse ' || TO_CHAR(i),
|
||||
CASE WHEN MOD(i, 2) = 0 THEN 'US' ELSE 'DE' END
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..5000 LOOP
|
||||
DECLARE
|
||||
l_on_hand NUMBER(12,2) := TRUNC(DBMS_RANDOM.VALUE(10, 1000));
|
||||
BEGIN
|
||||
INSERT INTO inventory_balances (
|
||||
product_id, warehouse_id, quantity_on_hand, quantity_reserved, last_counted_at
|
||||
) VALUES (
|
||||
MOD(i - 1, 500) + 1,
|
||||
TRUNC((i - 1) / 500) + 1,
|
||||
l_on_hand,
|
||||
TRUNC(DBMS_RANDOM.VALUE(0, l_on_hand + 1)),
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 30))
|
||||
);
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..10 LOOP
|
||||
INSERT INTO gl_accounts (account_code, account_name, account_type)
|
||||
VALUES (
|
||||
CASE i
|
||||
WHEN 1 THEN '1000' WHEN 2 THEN '1010' WHEN 3 THEN '1100'
|
||||
WHEN 4 THEN '2000' WHEN 5 THEN '2100' WHEN 6 THEN '3000'
|
||||
WHEN 7 THEN '4000' WHEN 8 THEN '4100' WHEN 9 THEN '5000'
|
||||
ELSE '5100'
|
||||
END,
|
||||
CASE i
|
||||
WHEN 1 THEN 'Cash' WHEN 2 THEN 'Payment Clearing' WHEN 3 THEN 'Inventory'
|
||||
WHEN 4 THEN 'Accounts Payable' WHEN 5 THEN 'Tax Payable' WHEN 6 THEN 'Equity'
|
||||
WHEN 7 THEN 'Product Revenue' WHEN 8 THEN 'Shipping Revenue'
|
||||
WHEN 9 THEN 'Cost of Goods Sold' ELSE 'Shipping Expense'
|
||||
END,
|
||||
CASE
|
||||
WHEN i <= 3 THEN 'ASSET'
|
||||
WHEN i <= 5 THEN 'LIABILITY'
|
||||
WHEN i = 6 THEN 'EQUITY'
|
||||
WHEN i <= 8 THEN 'REVENUE'
|
||||
ELSE 'EXPENSE'
|
||||
END
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..1000 LOOP
|
||||
INSERT INTO sales_orders (
|
||||
order_date, customer_id, channel_id, currency_id,
|
||||
billing_address_id, shipping_address_id, order_status,
|
||||
subtotal, tax_amount, shipping_amount
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
i, MOD(i - 1, 4) + 1, MOD(i - 1, 3) + 1, i, i,
|
||||
CASE WHEN MOD(i, 12) = 0 THEN 'CANCELLED'
|
||||
WHEN MOD(i, 5) = 0 THEN 'FULFILLED'
|
||||
ELSE 'PAID' END,
|
||||
ROUND(DBMS_RANDOM.VALUE(25, 1200), 2),
|
||||
ROUND(DBMS_RANDOM.VALUE(1, 100), 2),
|
||||
ROUND(DBMS_RANDOM.VALUE(0, 30), 2)
|
||||
);
|
||||
|
||||
FOR line_no IN 1..2 LOOP
|
||||
l_line_id := l_line_id + 1;
|
||||
INSERT INTO sales_order_lines (
|
||||
order_id, product_id, line_number, quantity, unit_price, discount_amount
|
||||
) VALUES (
|
||||
i, MOD(i * 2 + line_no - 2, 500) + 1, line_no,
|
||||
TRUNC(DBMS_RANDOM.VALUE(1, 5)),
|
||||
ROUND(DBMS_RANDOM.VALUE(5, 500), 2),
|
||||
ROUND(DBMS_RANDOM.VALUE(0, 10), 2)
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
INSERT INTO payments (
|
||||
payment_date, order_id, currency_id, payment_method,
|
||||
payment_status, amount, provider_reference
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
i, MOD(i - 1, 3) + 1,
|
||||
CASE MOD(i, 4) WHEN 0 THEN 'BANK' WHEN 1 THEN 'CARD'
|
||||
WHEN 2 THEN 'WALLET' ELSE 'CASH' END,
|
||||
CASE WHEN MOD(i, 17) = 0 THEN 'FAILED' ELSE 'CAPTURED' END,
|
||||
ROUND(DBMS_RANDOM.VALUE(25, 1300), 2),
|
||||
'PAY-' || TO_CHAR(i) || '-' || DBMS_RANDOM.STRING('X', 12)
|
||||
);
|
||||
|
||||
INSERT INTO shipments (
|
||||
shipped_at, order_id, warehouse_id, tracking_number, carrier_name, shipment_status
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
i, MOD(i - 1, 10) + 1, 'TRK-' || LPAD(TO_CHAR(i), 10, '0'),
|
||||
CASE MOD(i, 3) WHEN 0 THEN 'Parcel One' WHEN 1 THEN 'RapidShip' ELSE 'Global Freight' END,
|
||||
CASE WHEN MOD(i, 9) = 0 THEN 'IN_TRANSIT' ELSE 'DELIVERED' END
|
||||
);
|
||||
|
||||
INSERT INTO shipment_items (shipment_id, order_line_id, quantity)
|
||||
VALUES (i, (i - 1) * 2 + 1, 1);
|
||||
INSERT INTO shipment_items (shipment_id, order_line_id, quantity)
|
||||
VALUES (i, (i - 1) * 2 + 2, 1);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..100 LOOP
|
||||
INSERT INTO purchase_orders (
|
||||
ordered_at, supplier_id, warehouse_id, currency_id, purchase_status
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
MOD(i - 1, 50) + 1, MOD(i - 1, 10) + 1, MOD(i - 1, 3) + 1,
|
||||
CASE WHEN MOD(i, 6) = 0 THEN 'ORDERED' ELSE 'RECEIVED' END
|
||||
);
|
||||
|
||||
FOR line_no IN 1..2 LOOP
|
||||
l_purchase_line_id := l_purchase_line_id + 1;
|
||||
INSERT INTO purchase_order_lines (
|
||||
purchase_order_id, product_id, line_number, quantity, unit_cost
|
||||
) VALUES (
|
||||
i, MOD(i * 2 + line_no - 2, 500) + 1, line_no,
|
||||
TRUNC(DBMS_RANDOM.VALUE(10, 200)),
|
||||
ROUND(DBMS_RANDOM.VALUE(3, 300), 2)
|
||||
);
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..2000 LOOP
|
||||
INSERT INTO inventory_movements (
|
||||
movement_at, product_id, warehouse_id, order_line_id,
|
||||
movement_type, quantity_delta, reference_note
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
MOD(i - 1, 500) + 1, MOD(TRUNC((i - 1) / 500), 10) + 1,
|
||||
MOD(i - 1, 2000) + 1,
|
||||
'SALE', -1, 'Generated fulfillment movement'
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..1000 LOOP
|
||||
l_journal_amount := ROUND(DBMS_RANDOM.VALUE(25, 1300), 2);
|
||||
INSERT INTO journal_entries (
|
||||
posted_at, currency_id, source_type, source_id, entry_status, memo
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
MOD(i - 1, 3) + 1, 'SALES_ORDER', i, 'POSTED',
|
||||
'Generated balanced sales posting ' || TO_CHAR(i)
|
||||
);
|
||||
|
||||
l_journal_line_id := l_journal_line_id + 1;
|
||||
INSERT INTO journal_lines (
|
||||
journal_entry_id, account_id, line_number, debit_amount, credit_amount, line_memo
|
||||
) VALUES (
|
||||
i, 1, 1, l_journal_amount, 0, 'Cash or clearing debit'
|
||||
);
|
||||
|
||||
l_journal_line_id := l_journal_line_id + 1;
|
||||
INSERT INTO journal_lines (
|
||||
journal_entry_id, account_id, line_number, debit_amount, credit_amount, line_memo
|
||||
) VALUES (
|
||||
i, 7, 2, 0, l_journal_amount, 'Sales revenue credit'
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
FOR i IN 1..100 LOOP
|
||||
INSERT INTO returns (
|
||||
returned_at, order_line_id, customer_id, return_status, quantity, reason_code
|
||||
) VALUES (
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
MOD(i - 1, 2000) + 1, TRUNC((MOD(i - 1, 2000)) / 2) + 1,
|
||||
CASE WHEN MOD(i, 4) = 0 THEN 'REFUNDED' ELSE 'RECEIVED' END,
|
||||
1, CASE MOD(i, 3) WHEN 0 THEN 'DAMAGED' WHEN 1 THEN 'NOT_AS_DESCRIBED' ELSE 'CHANGED_MIND' END
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
COMMIT;
|
||||
DBMS_OUTPUT.PUT_LINE('Reference and transactional sample data inserted.');
|
||||
|
||||
l_rows := CEIL(c_target_payload_bytes / c_payload_chars);
|
||||
l_offset := 1;
|
||||
WHILE l_offset <= l_rows LOOP
|
||||
l_batch_rows := LEAST(l_batch_size, l_rows - l_offset + 1);
|
||||
|
||||
INSERT INTO audit_events (
|
||||
event_at, actor_customer_id, event_type, source_ip, details
|
||||
)
|
||||
SELECT
|
||||
TRUNC(SYSDATE) - TRUNC(DBMS_RANDOM.VALUE(0, 365)),
|
||||
CASE WHEN DBMS_RANDOM.VALUE(0, 1) < 0.8
|
||||
THEN TRUNC(DBMS_RANDOM.VALUE(1, 1001)) ELSE NULL END,
|
||||
CASE MOD(LEVEL, 5)
|
||||
WHEN 0 THEN 'CUSTOMER_LOGIN'
|
||||
WHEN 1 THEN 'PRODUCT_VIEW'
|
||||
WHEN 2 THEN 'ORDER_UPDATE'
|
||||
WHEN 3 THEN 'PAYMENT_EVENT'
|
||||
ELSE 'ADDRESS_CHANGE'
|
||||
END,
|
||||
'192.0.2.' || TO_CHAR(TRUNC(DBMS_RANDOM.VALUE(1, 255))),
|
||||
DBMS_RANDOM.STRING(
|
||||
'A',
|
||||
LEAST(
|
||||
c_payload_chars,
|
||||
c_target_payload_bytes -
|
||||
((l_offset + LEVEL - 2) * c_payload_chars)
|
||||
)
|
||||
)
|
||||
FROM dual
|
||||
CONNECT BY LEVEL <= l_batch_rows;
|
||||
|
||||
COMMIT;
|
||||
l_offset := l_offset + l_batch_rows;
|
||||
IF MOD(l_offset - 1, 50000) < l_batch_rows THEN
|
||||
DBMS_OUTPUT.PUT_LINE(
|
||||
'Audit events generated: ' || TO_CHAR(LEAST(l_offset - 1, l_rows)) ||
|
||||
' / ' || TO_CHAR(l_rows)
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE(
|
||||
'Completed audit payload: ' || TO_CHAR(l_rows) ||
|
||||
' rows x ' || TO_CHAR(c_payload_chars) ||
|
||||
' characters (~2 GiB), plus Oracle row and index overhead.'
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT Random dataset generation complete.
|
||||
Reference in new issue
Block a user