diff --git a/mysql-json-duality/connect-mysql-heatwave/connect-mysql-heatwave.md b/mysql-json-duality/connect-mysql-heatwave/connect-mysql-heatwave.md new file mode 100644 index 000000000..6178bde0d --- /dev/null +++ b/mysql-json-duality/connect-mysql-heatwave/connect-mysql-heatwave.md @@ -0,0 +1,86 @@ +# Connect to MySQL HeatWave DB system + +## Introduction + +Modern application development demands tools that reduce context switching and improve developer productivity. The MySQL Shell extension for Visual Studio Code brings powerful database interaction directly into your development workspace. + +With seamless support for SQL, Javascript, and TypeScript right inside the familiar VS Code environment developers can connect, query, and script against MySQL databases without ever leaving their IDE. + +In this lab, you'll learn how to connect to a MySQL DB system using the MySQL Shell extension in Visual Studio Code. This setup is especially useful if you are working in a development environment and prefer using VS code interface to manage your databases. + +Estimated time: 10 minutes + +### Objectives + +* Connect to a MySQL DB system using MySQL Shell extension for VS Code + +## Task 1: Connect to a MySQL DB system using MySQL Shell extension for VS Code + +1. Launch Visual Studio Code and click on the **MySQL Shell for VS Code icon** in the left sidebar. This opens the database panel where you can add and manage connections. + + ![Launch VS Code](./images/launch-vs-code.png " ") + +2. Click the **+ New Connection** button within the Database Connections panel or on the home tab. Either ways will work to create a new connection. + + ![Add New Connection](./images/add-new-connection.png " ") + +3. This opens up a new connection tab to fill in the required details in the dialog box. + + ![Fill Connection Details](./images/fill-connection-details.png " ") + +4. Fill in the required fields: + + * **Caption**: A friendly name for your connection. In this example, use **HeatWave_DB** + * **Description**: An optional but helpful description. Use **HeatWave_DB** as the description + * **Host Name or IP Address**: Enter the hostname which you copied from the connections tab of the MySQL HeatWave DB system + * **Port**: This is the port your MySQL server is running on. Typically, it is **3306** + * **Username**: Enter the username as **admin** + + ![Filled Connection Details](./images/connection-filled-details.png " ") + +5. Once you filled in the above details, click on **Store Password** to minimize entering the password every time for convenience. Enter password as **Welcome1!** to connect to the host. + + ![Store Password](./images/store-password.png " ") + +6. Once the password is entered, click on **OK** to save the password. + + ![Filled Password](./images/filled-password.png " ") + +7. You can securely connect to your HeatWave MySQL DB system using an SSH tunnel through a compute instance, which acts as a jump host or bastion host. OCI also provides the Bastion service as an alternative for secure access to private resources. + +8. Check Connect Using SSH Tunnel box under Tunneling options. + + ![SSH Tunnel](./images/check-ssh-tunneling.png " ") + +9. Expand the SSH tunnel section and configure: + +* SSH Host: Public IP or hostname of your Compute instance +* SSH Port: 22 (default SSH port) +* SSH Username: Username for the Compute instance (e.g., opc on Oracle Linux) +* SSH Key: Browse and Select your private key file + + ![SSH Tunnel](./images/ssh-tunneling.png " ") + +10. After all the details are entered, click on **OK** to save connection to the MySQL DB system. + + ![Click OK](./images/click-ok.png " ") + +> **Note:** _The MySQL Shell extension with route your connection securely through the tunnel._ + +11. If the connection is successful, you will see a connection created and the MySQL DB system connection name appears under Database Connections as well. + + ![Connection Created](./images/connection-created.png " ") + +12. Clicking on the connection opens MySQL Shell DB Notebook for MySQL DB system. + + ![Notebook Interface](./images/notebook-interface.png " ") + +13. You can also connect to your MySQL DB system from the left bar navigation by clicking on the **notebook** icon beside the connection name. + + ![Notebook Connection](./images/notebook-connection.png " ") + +## Acknowledgements + +* **Author** - Sindhuja Banka, MySQL HeatWave Product Manager +* **Contributors** - Sindhuja Banka +* **Last Updated By/Date** - Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/connect-mysql-heatwave/images/add-new-connection.png b/mysql-json-duality/connect-mysql-heatwave/images/add-new-connection.png new file mode 100644 index 000000000..13d8be66c Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/add-new-connection.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/check-ssh-tunneling.png b/mysql-json-duality/connect-mysql-heatwave/images/check-ssh-tunneling.png new file mode 100644 index 000000000..868952d7e Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/check-ssh-tunneling.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/click-ok.png b/mysql-json-duality/connect-mysql-heatwave/images/click-ok.png new file mode 100644 index 000000000..104b014cc Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/click-ok.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/connection-created.png b/mysql-json-duality/connect-mysql-heatwave/images/connection-created.png new file mode 100644 index 000000000..19c05a945 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/connection-created.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/connection-filled-details.png b/mysql-json-duality/connect-mysql-heatwave/images/connection-filled-details.png new file mode 100644 index 000000000..9b746fe58 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/connection-filled-details.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/fill-connection-details.png b/mysql-json-duality/connect-mysql-heatwave/images/fill-connection-details.png new file mode 100644 index 000000000..380fbbcf7 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/fill-connection-details.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/filled-password.png b/mysql-json-duality/connect-mysql-heatwave/images/filled-password.png new file mode 100644 index 000000000..9228e34eb Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/filled-password.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/launch-vs-code.png b/mysql-json-duality/connect-mysql-heatwave/images/launch-vs-code.png new file mode 100644 index 000000000..578e0e744 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/launch-vs-code.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/notebook-connection.png b/mysql-json-duality/connect-mysql-heatwave/images/notebook-connection.png new file mode 100644 index 000000000..fd25341cc Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/notebook-connection.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/notebook-interface.png b/mysql-json-duality/connect-mysql-heatwave/images/notebook-interface.png new file mode 100644 index 000000000..174bb5873 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/notebook-interface.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/ssh-tunneling.png b/mysql-json-duality/connect-mysql-heatwave/images/ssh-tunneling.png new file mode 100644 index 000000000..0690e8f19 Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/ssh-tunneling.png differ diff --git a/mysql-json-duality/connect-mysql-heatwave/images/store-password.png b/mysql-json-duality/connect-mysql-heatwave/images/store-password.png new file mode 100644 index 000000000..063af903b Binary files /dev/null and b/mysql-json-duality/connect-mysql-heatwave/images/store-password.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compartment-completed.png b/mysql-json-duality/create-mysql-heatwave/images/compartment-completed.png new file mode 100644 index 000000000..cea6a81e4 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compartment-completed.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compartment-details.png b/mysql-json-duality/create-mysql-heatwave/images/compartment-details.png new file mode 100644 index 000000000..1383d30cb Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compartment-details.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-active.png b/mysql-json-duality/create-mysql-heatwave/images/compute-active.png new file mode 100644 index 000000000..b24804360 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-active.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create-click.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create-click.png new file mode 100644 index 000000000..cc30f4764 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create-click.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create-info.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create-info.png new file mode 100644 index 000000000..e3f96bc57 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create-info.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create-security.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create-security.png new file mode 100644 index 000000000..b3b904959 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create-security.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create-storage.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create-storage.png new file mode 100644 index 000000000..b37b87fb8 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create-storage.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create-vnic.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create-vnic.png new file mode 100644 index 000000000..bee4d5f7f Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create-vnic.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-create.png b/mysql-json-duality/create-mysql-heatwave/images/compute-create.png new file mode 100644 index 000000000..b22789493 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-create.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-menu-create-instance.png b/mysql-json-duality/create-mysql-heatwave/images/compute-menu-create-instance.png new file mode 100644 index 000000000..b19929adc Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-menu-create-instance.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/compute-provisioning.png b/mysql-json-duality/create-mysql-heatwave/images/compute-provisioning.png new file mode 100644 index 000000000..3cde8630d Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/compute-provisioning.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/create-compartment.png b/mysql-json-duality/create-mysql-heatwave/images/create-compartment.png new file mode 100644 index 000000000..14b14cbda Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/create-compartment.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-active.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-active.png new file mode 100644 index 000000000..7090997f1 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-active.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-admin.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-admin.png new file mode 100644 index 000000000..677d9d453 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-admin.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-basic.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-basic.png new file mode 100644 index 000000000..4a4f97d85 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-basic.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-backup.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-backup.png new file mode 100644 index 000000000..5273a9ef2 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-backup.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-database-version.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-database-version.png new file mode 100644 index 000000000..ba3ee6343 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-database-version.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-hardware.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-hardware.png new file mode 100644 index 000000000..c401356c0 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-hardware.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-version.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-version.png new file mode 100644 index 000000000..e94b3d68e Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-configure-version.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-create-menu.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-create-menu.png new file mode 100644 index 000000000..35d02aafe Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-create-menu.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-development.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-development.png new file mode 100644 index 000000000..701f503c0 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-development.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-networking.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-networking.png new file mode 100644 index 000000000..e9be68b32 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-networking.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-placement.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-placement.png new file mode 100644 index 000000000..933036656 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-placement.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql-standalone.png b/mysql-json-duality/create-mysql-heatwave/images/mysql-standalone.png new file mode 100644 index 000000000..52bc5657b Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql-standalone.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/mysql_creating.png b/mysql-json-duality/create-mysql-heatwave/images/mysql_creating.png new file mode 100644 index 000000000..1ecba7db6 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/mysql_creating.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/policy-builder.png b/mysql-json-duality/create-mysql-heatwave/images/policy-builder.png new file mode 100644 index 000000000..9298f92e2 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/policy-builder.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/policy-create.png b/mysql-json-duality/create-mysql-heatwave/images/policy-create.png new file mode 100644 index 000000000..68f3f6502 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/policy-create.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/policy-page.png b/mysql-json-duality/create-mysql-heatwave/images/policy-page.png new file mode 100644 index 000000000..24db13bcf Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/policy-page.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-basic.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-basic.png new file mode 100644 index 000000000..dfd46cc55 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-basic.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-create.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-create.png new file mode 100644 index 000000000..1f1b7bfac Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-create.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-input.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-input.png new file mode 100644 index 000000000..bfc75397e Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-input.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-page.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-page.png new file mode 100644 index 000000000..6ab0c5a50 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules-page.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules.png new file mode 100644 index 000000000..b218b727c Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-private-subnet-ingress-rules.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-review.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-review.png new file mode 100644 index 000000000..342f877e0 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-review.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-security-list.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-security-list.png new file mode 100644 index 000000000..4b33d8f8e Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-security-list.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-start-select.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-start-select.png new file mode 100644 index 000000000..6bd285fd2 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-start-select.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-start.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-start.png new file mode 100644 index 000000000..b6e7352d6 Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-start.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/images/vcn-view.png b/mysql-json-duality/create-mysql-heatwave/images/vcn-view.png new file mode 100644 index 000000000..aa474d37a Binary files /dev/null and b/mysql-json-duality/create-mysql-heatwave/images/vcn-view.png differ diff --git a/mysql-json-duality/create-mysql-heatwave/mysql-heatwave.md b/mysql-json-duality/create-mysql-heatwave/mysql-heatwave.md new file mode 100644 index 000000000..6850cd532 --- /dev/null +++ b/mysql-json-duality/create-mysql-heatwave/mysql-heatwave.md @@ -0,0 +1,284 @@ +# Create MySQL HeatWave DB system + +## Introduction + +In this lab, you will learn how to launch a MySQL HeatWave DB system on Oracle Cloud Infrastructure (OCI) and later connect to it using MySQL Shell extension for Visual Studio Code. + +Estimated Time: 20 minutes + +### About MySQL HeatWave Service + +MySQL HeatWave is a fully-managed OCI service that is developed, managed, and supported by the MySQL team in Oracle. + +### Objectives + +In this lab, you will be guided through the following steps: + +- Create a compartment +- Create a policy +- Create a virtual cloud network (VCN) +- Create a MySQL HeatWave DB system +- Create a client virtual machine + +### Prerequisites + +- An Oracle Free Tier, Always Free, Paid or LiveLabs Cloud Account +- Some Experience with MySQL Shell +- Create a local Secure Shell (SSH) key + +## Task 1: Create a Compartment + +You must have an OCI tenancy subscribed to your home region and enough limits configured for your tenancy to create a MySQL HeatWave Database System. Make sure to log in to the Oracle Cloud Console as an Administrator. + +1. Click the **Navigation Menu** in the upper left, navigate to **Identity & Security** and select **Compartments**. + + ![Oracle Cloud Console](https://oracle-livelabs.github.io/common/images/console/id-compartment.png "Oracle Cloud Console") + +2. On the Compartments page, click **Create Compartment**. + + ![Compartment2](./images/create-compartment.png "In Compartments page ") + + > **Note:** Two Compartments, _Oracle Account Name_ (root) and a compartment for PaaS, were automatically created by the Oracle Cloud. + +3. In the Create Compartment dialog box, in the **NAME** field, enter **HeatWave_Sandbox**, and then enter a Description, select the **Parent Compartment**, and click **Create compartment**. + + ![Create a Compartment](./images/compartment-details.png "Enter Compartment Details") + + The following screen shot shows a completed compartment: + + ![Completed Compartment](./images/compartment-completed.png "Completed compartment") + +## Task 2: Create a Policy + +1. Click the **Navigation Menu** in the upper-left corner, navigate to **Identity & Security** and select **Policies**. + + ![Navigation Menu](https://oracle-livelabs.github.io/common/images/console/id-policies.png "Navigation Menu") + +2. On the Policies page, in the **List Scope** section, select the Compartment (root) and click **Create Policy**. + + ![Policies page](./images/policy-page.png "Policies page") + +3. On the Create Policy page, in the **Description** field, enter **HeatWave_Policy** and select the root compartment. + +4. In the **Policy Builder** section, turn on the **Show manual editor** toggle switch. + + ![Create Policy page](./images/policy-builder.png "Create Policy page") + +5. Enter the following required MySQL HeatWave policies: + + - Policy statement 1: + + ```bash + Allow group Administrators to {COMPARTMENT_INSPECT} in tenancy + ``` + + - Policy statement 2: + + ```bash + Allow group Administrators to {VCN_READ, SUBNET_READ, SUBNET_ATTACH, SUBNET_DETACH} in tenancy + ``` + + - Policy statement 3: + + ```bash + Allow group Administrators to manage mysql-family in tenancy + ``` + +6. Click **Create**. + + ![Create Policy page](./images/policy-create.png "Create Policy page") + +## Task 3: Create a VCN + +1. Click the **Navigation Menu** in the upper-left corner, navigate to **Networking**, and select **Virtual Cloud Networks**. + + ![Virtual Cloud Networks](https://oracle-livelabs.github.io/common/images/console/networking-vcn.png "Virtual Cloud Networks") + +2. Click **Start VCN Wizard**. + +3. Select **VCN with Internet Connectivity** and click **Start VCN Wizard**. + + ![Start VCN Wizard](./images/vcn-start.png "Start VCN Wizard") + ![Start VCN Wizard Select](./images/vcn-start-select.png "Start VCN Wizard Select") + + + +4. On the Create a VCN with Internet Connectivity page, in the **Basic Information** section, in the **VCN Name** field, enter `HeatWave_VCN` and from the **Compartment** drop-down list, select **HeatWave_Sandbox**. + > **Note:** Your screen should look similar to the following screen shot: + + ![VCN with Internet Connectivity page](./images/vcn-basic.png "VCN with Internet Connectivity page") + +5. Click **Next** at the bottom of the screen. + +6. Review the **Oracle Virtual Cloud Network (VCN)**, **Subnets**, and **Gateways** sections and click **Create** to create the VCN. + + ![VCN](./images/vcn-review.png "VCN Review") + + > **Note:** The VCN creation is completing. + + ![VCN creation page](./images/vcn-create.png "VCN creation page") + +7. Click **View Virtual Cloud Network** to display the created VCN. + + ![View Virtual Cloud Network](./images/vcn-view.png "View Virtual Cloud Network") + + +8. On the Virtual Cloud Network Details page, select the **Security** tab, click on **Security List for Private Subnet-HeatWave_VCN** + + ![Security Lists](./images/vcn-security-list.png "VCN Security Lists") + +## Task 4: Configure security list to allow MySQL incoming connection HeatWave_VCNs + +1. In the **Security List for Private Subnet-HeatWave_VCN** section, in the **Ingress Rules** section, click **Add Ingress Rules**. + + ![Ingress Rules](./images/vcn-private-subnet-ingress-rules.png "Ingress Rules") + +2. In the **Add Ingress Rule** dialog box, add an ingress rule with **Source CIDR** `0.0.0.0/0` and destination port number `3306, 33060` and click **Add Ingress Rule**. + + ![MySQL Port](./images/vcn-private-subnet-ingress-rules-input.png "MySQL Port") + +3. On the Security List for Private Subnet-HeatWave_VCN page, the new ingress rules will be shown in the **Ingress Rules** list. + + ![Private Subnet-HeatWave_VCN page](./images/vcn-private-subnet-ingress-rules-page.png "Private Subnet-HeatWave_VCN page") + +## Task 5: Create a MySQL HeatWave DB system + +1. Click the **Navigation Menu** in the upper-left corner, navigate to **Databases**, and select **Database Systems**. + + ![Database Systems](https://oracle-livelabs.github.io/common/images/console/database-dbsys.png "Database Systems") + +2. Click **Create MySQL HeatWave Database System**. + + ![Create Database System](./images/mysql-create-menu.png "MySQL Create Database System") + +3. Select the Development or Testing Option + + ![Development](./images/mysql-development.png "Select Development") + +4. On the Create MySQL HeatWave Database System dialog box, complete the fields in each section: + + - Provide basic information for the database system + - Set up your required database system + - Create administrator credentials + - Configure networking + - Configure placement + - Configure hardware + - Configure backups + - Show advanced options + +5. In **Provide basic information for the DB System**, select the **HeatWave\_Sandbox** Compartment, in the **Name** field and **Description** field, enter **HeatWave_DB**. + + ![Create MySQL HeatWave Database Basic](./images/mysql-basic.png "Create MySQL HeatWave Database Basic") + +6. In **Create Administrator credentials**, enter **admin** for the user name, enter **Welcome1!** for the password, and then enter **Welcome1!** to confirm the password. + + ![HeatWave](./images/mysql-admin.png "MySQL Admin ") + +7. In **Setup your required Database System**, select **Standalone** to specify a single-instance database system. + + ![Standalone](./images/mysql-standalone.png "Standalone") + +8. In **Configure networking**, keep default values **HeatWave\_VCN** for the VCH and **private subnet-HeatWave\_VCN (Regional)** for the subnet. + + ![Configure networking](./images/mysql-networking.png "Configure networking") + +9. In **Configure placement**, keep **Availability Domain** selected. + + > **Note:** Do not select **Choose a Fault Domain** for this database system. Oracle will select the best placement for you. + + ![Configure placement](./images/mysql-placement.png "MySQL Configure placement") + +10. In **Configure hardware**: + - Remove the check mark from **Enable HeatWave** + - Set the default shape to **MySQL.2** + - Set the value **100** for the **Data Storage Size (GB)**. + + ![MySQL HardWare](./images/mysql-configure-hardware.png "MySQL Configure HardWare") + +11. In **Configure Backups**, keep **Enable Automatic Backups** selected. Set the retention period to `7` and select **Default Backup Window**. + + ![Configure Backups](./images/mysql-configure-backup.png "Configure Backups") + +12. Expand advanced options at the end to select the database version. + + ![Configure Version](./images/mysql-configure-version.png "Configure Version") + +13. Expand Configuration tab under advanced options to select the database version to **9.4.1** and click **Create**. + + ![Configure Version](./images/mysql-configure-database-version.png "Configure Version") + + > **Note:** The New MySQL HeatWave Database System will be ready to use after a few minutes. The state will be shown as **Creating** during the creation. + + ![Creating DB](./images/mysql_creating.png "Creating DB") + + > **Note:** The **Active** state indicates that the database system is ready to use. + +14. The state **Active** indicates that the DB system is ready for use. On the **HeatWave_DB** page,select the **Connections** tab, check and save the Endpoint (Private IP Address). Later, you will need this value to connect to the Heatwave DB using the MySQL Shell client tool. + + ![HeatWave Details page](./images/mysql-active.png "MySQL Details page") + +## Task 6: Create the Client Virtual Machine + +> **Important:** If you have not already completed the **Create Local SSH Key** lab, please do so now. When you are finished, return to this task. + +1. You need a client machine to connect to your brand new MySQL database. Click the **Navigation Menu** in the upper-left corner, navigate to **Compute**, and select **Instances**. + + ![Compute Menu](https://oracle-livelabs.github.io/common/images/console/compute-instances.png "Compute Menu") + +2. In the **Instances in HeatWave_Sandbox Compartment** section, click **Create Instance**. + + ![Compute Instance Menu](./images/compute-menu-create-instance.png "Compute Instance Menu") + +3. In the **Create Compute Instance** section, enter **HeatWave_Client** for the instance name. + +4. Make sure the **HeatWave_Sandbox** compartment is selected. + +5. Choose an operating system or image source (for this lab, select **Oracle Linux**). + +6. In the **Configure placement and hardware** section, keep the default **Availability Domain** and keep the default **Shape**. + + ![Configure placement and hardware](./images/compute-create-info.png "Configure placement and hardware") + + > **Note:** For the **Security** section, click Next + ![Configure security](./images/compute-create-security.png "Configure security") + + > **Note:** **Virtual cloud network**, make sure **HeatWave_VCN** is selected and **Assign a public IPv4 address** is **selected** + + ![Assign a public IPv4 address](./images/compute-create-vnic.png "Assign a public IPv4 address") + +7. If you have not already created your SSH key, complete the **Create Local SSH Key** lab. When you are done, continue on to the next step. + +8. In the **Add SSH keys** section, generate an SSH key pair or upload your own public key. Select one of the following options: + + - **Generate SSH key pair:** Oracle Cloud Infrastructure (OCI) generates an RSA key pair for the instance. Click **Save Private Key**, and then save the private key on your computer. Optionally, click **Save Public Key** and then save the public key. + - **Choose public key files:** Upload the public key portion of your key pair. Either browse to the key file that you want to upload, or drag and drop the file into the field. To provide multiple keys, press and hold down the Command key (on Mac) or the CTRL key (on Windows) while selecting files. + - **Paste public keys:** Paste the public key portion of your key pair in the field. + - **No SSH keys:** Do _not_ select this option. You will not be able to connect to the compute instance using SSH. + + ![SSH key pair](./images/compute-create.png "SSH key pair") + + > **Note:** For the **Storage** section, click Next + ![Configure storage](./images/compute-create-storage.png "Configure storage") + +9. Click the Create **button** + + ![Click create](./images/compute-create-click.png "Click create") + **Note:** The new virtual machine will be ready to use after a few minutes. The state will be shown as **Provisioning** during the creation. + + ![Compute Provisioning](./images/compute-provisioning.png "Compute Provisioning") + + > **Note:** The **Running** state indicates that the virtual machine is ready for use. **Save the Public IP Address** is under **Instance Access** on the **HeatWave_Client** page. + + ![Compute Active](./images/compute-active.png "Compute Active") + +## Learn More + +- [MySQL Heatwave Documentation](https://docs.oracle.com/en-us/iaas/mysql-database/) + +- [MySQL HeatWave Database Documentation](https://www.mysql.com) + +## Acknowledgements + +- **Author** - Sindhuja Banka, MySQL Product Manager +- **Contributors** - Sindhuja Banka +- **Last Updated By/Date** - Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/create-schema/create-schema.md b/mysql-json-duality/create-schema/create-schema.md new file mode 100644 index 000000000..678f055ac --- /dev/null +++ b/mysql-json-duality/create-schema/create-schema.md @@ -0,0 +1,230 @@ +# Creating the Schema for JSON Duality Views + +## Introduction + +This lab guides you through the foundational steps required to set up a hospital database, its core relational tables, and initial data. This serves as the groundwork for exploring JSON Duality Views in upcoming lab sections. By the end, you’ll have a populated hospital database ready to leverage MySQL's dual relational/JSON capabilities. + +Estimated Lab Time: 10 minutes + +### Objectives + +In this lab, you will be guided through the following tasks: + +- Create the database and relational tables +- Populate the database with sample data needed for duality views + +### Prerequisites + +- An Oracle Trial or Paid Cloud Account +- Some Experience with MySQL +- Completed Lab 3 + +## Task 1: Create the database and relational tables + +1. Let us begin by creating a database called **hospital** to add the relational tables. + + ``` + CREATE DATABASE hospital; + ``` + ![Execute Query](./images/create-database.png " ") + +2. Switch to the newly created hospital database. + + ``` + USE hospital; + ``` + ![Execute Query](./images/use-database.png " ") + +3. Once the database is created, we need to set up four key tables: patients, doctors, appointments, and lab reports. +These tables will store the main information for our hospital database, and later on, we’ll use them to build JSON Duality Views, which allow you to see and work with this data in both relational and JSON formats. + +4. The patients table will store demographic and medical data for each patient, serving as a key entity for the hospital schema. + + ``` + CREATE TABLE patients ( + patient_id INT PRIMARY KEY, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + dob DATE DEFAULT NULL, + gender ENUM('Male', 'Female', 'Other') DEFAULT NULL, + contact_number VARCHAR(15) DEFAULT NULL, + email VARCHAR(100) DEFAULT NULL, + address TEXT DEFAULT NULL, + medical_history TEXT DEFAULT NULL +); + + ``` + ![Execute Query](./images/patients-table.png " ") + +5. The doctors table holds information about healthcare providers and is related to both appointments and lab reports. + + ``` + + CREATE TABLE doctors ( + doctor_id INT PRIMARY KEY, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + specialty VARCHAR(100) DEFAULT NULL, + contact_number VARCHAR(15) DEFAULT NULL, + email VARCHAR(100) DEFAULT NULL, + department VARCHAR(100) DEFAULT NULL +); + + ``` + ![Execute Query](./images/doctors-table.png " ") + +6. The Appointments connect patients and doctors and record scheduled meetings, including their dates, status, and remarks. + + ``` + + CREATE TABLE appointments ( + appointment_id INT PRIMARY KEY, + patient_id INT NOT NULL, + doctor_id INT NOT NULL, + appointment_time DATETIME NOT NULL, + status ENUM('Scheduled', 'Completed', 'Cancelled') DEFAULT 'Scheduled', + notes TEXT DEFAULT NULL, + FOREIGN KEY (patient_id) REFERENCES patients(patient_id), + FOREIGN KEY (doctor_id) REFERENCES doctors(doctor_id) +); + + ``` + ![Execute Query](./images/appointments-table.png " ") + +7. Then Lab reports table tracks all laboratory test results for patients and records which doctor ordered or supervised them. + + ``` + + CREATE TABLE lab_reports ( + report_id INT PRIMARY KEY, + patient_id INT NULL, + doctor_id INT DEFAULT NULL, + test_name VARCHAR(255) DEFAULT NULL, + test_date DATE DEFAULT NULL, + results TEXT DEFAULT NULL, + remarks TEXT DEFAULT NULL, + FOREIGN KEY (patient_id) REFERENCES patients(patient_id), + FOREIGN KEY (doctor_id) REFERENCES doctors(doctor_id) +); + + ``` + ![Execute Query](./images/labreports-table.png " ") + +## Task 2: Insert records into the table + +1. Add initial doctors to the doctors table to make relationships possible and have realistic datasets for querying and duality view experiments. + + ``` + + INSERT INTO doctors (doctor_id, first_name, last_name, specialty, contact_number, email, department) VALUES + (1, 'John', 'Doe', 'Cardiology', '1234567890', 'johndoe@example.com', 'Cardiology'), + (2, 'Sarah', 'Smith', 'Neurology', '1234567891', 'sarahsmith@example.com', 'Neurology'), + (3, 'James', 'Brown', 'Pediatrics', '1234567892', 'jamesbrown@example.com', 'Pediatrics'), + (4, 'Emily', 'Davis', 'Orthopedics', '1234567893', 'emilydavis@example.com', 'Orthopedics'), + (5, 'Michael', 'Wilson', 'General Medicine', '1234567894', 'michaelwilson@example.com', 'General Medicine'); + + ``` + ![Execute Query](./images/insert-doctors.png " ") + +2. Insert sample patients as these patients allow you to simulate various appointments and lab tests. + + ``` + + INSERT INTO patients (patient_id, first_name, last_name, dob, gender, contact_number, email, address, medical_history) VALUES + (1, 'Alice', 'Johnson', '1985-06-15', 'Female', '9876543210', 'alicejohnson@example.com', '123 Elm Street', 'Diabetes'), + (2, 'Robert', 'Williams', '1990-09-22', 'Male', '9876543211', 'robertwilliams@example.com', '456 Oak Avenue', 'Hypertension'), + (3, 'Sophia', 'Martinez', '2000-01-05', 'Female', '9876543212', 'sophiamartinez@example.com', '789 Maple Lane', 'Asthma'), + (4, 'David', 'Anderson', '1982-04-17', 'Male', '9876543213', 'davidanderson@example.com', '159 Pine Road', 'No known conditions'), + (5, 'Emma', 'Harris', '1995-07-30', 'Female', '9876543214', 'emmaharris@example.com', '753 Birch Blvd', 'Migraine'), + (6, 'Daniel', 'Thomas', '1988-11-12', 'Male', '9876543215', 'danielthomas@example.com', '951 Cedar Dr', 'Allergic to Penicillin'), + (7, 'Olivia', 'White', '1975-12-25', 'Female', '9876543216', 'oliviawhite@example.com', '852 Spruce St', 'High Cholesterol'); + + ``` + ![Execute Query](./images/insert-patients.png " ") + +3. Insert Sample appointments to Connect patients and doctors with a set of realistic appointments. This is essential for join queries and dual views later on. + + ``` + + INSERT INTO appointments (appointment_id, patient_id, doctor_id, appointment_time, status, notes) VALUES + (1, 1, 1, '2024-02-05 10:00:00', 'Scheduled', 'Routine check-up'), + (2, 2, 3, '2024-02-06 11:30:00', 'Scheduled', 'Follow-up on hypertension medication'), + (3, 3, 2, '2024-02-07 14:00:00', 'Scheduled', 'Neurology consultation'), + (4, 4, 4, '2024-02-08 09:15:00', 'Scheduled', 'Orthopedic assessment for knee pain'), + (5, 5, 5, '2024-02-09 16:45:00', 'Scheduled', 'General health check-up'), + (6, 6, 1, '2024-02-10 12:00:00', 'Scheduled', 'Heart condition follow-up'), + (7, 7, 2, '2024-02-11 15:30:00', 'Scheduled', 'MRI scan review'); + + ``` + ![Execute Query](./images/insert-appointments.png " ") + +4. This data supports scenarios involving diagnostic results and enables you to explore JSON document construction in future steps. + + ``` + + INSERT INTO lab_reports (report_id, patient_id, doctor_id, test_name, test_date, results, remarks) VALUES + (1, 1, 1, 'Blood Sugar Test', '2024-02-01', 'Fasting: 110 mg/dL, Post-meal: 140 mg/dL', 'Slightly elevated, monitor regularly'), + (2, 2, 3, 'Lipid Profile', '2024-02-02', 'Total Cholesterol: 220 mg/dL, LDL: 150 mg/dL', 'High cholesterol, dietary changes recommended'), + (3, 3, 2, 'MRI Brain Scan', '2024-02-03', 'No abnormalities detected', 'Normal scan, no concerns'), + (4, 4, 4, 'X-ray Knee', '2024-02-04', 'Mild arthritis detected', 'Physical therapy suggested'), + (5, 5, 5, 'Complete Blood Count', '2024-02-05', 'Normal hemoglobin levels', 'No issues detected'); + + ``` + ![Execute Query](./images/insert-labreports.png " ") + +5. Insert Additional Lab Reports adding more variety and depth to the lab data, simulating multiple tests for patients. + + ``` + + INSERT INTO lab_reports (report_id, patient_id, doctor_id, test_name, test_date, results, remarks) VALUES + + -- Reports for patient 1 (Alice Johnson) + (6, 1, 1, 'Cholesterol Test', '2024-02-10', 'Total: 200 mg/dL, LDL: 120 mg/dL', 'Normal levels, maintain diet.'), + (7, 1, 2, 'ECG', '2024-02-15', 'No abnormalities detected', 'Healthy heart rhythm.'), + (8, 1, 3, 'Vitamin D Test', '2024-02-20', 'Vitamin D: 22 ng/mL', 'Slightly low, consider supplements.'), + + -- Reports for patient 2 (Robert Williams) + (9, 2, 3, 'Kidney Function Test', '2024-02-08', 'Creatinine: 1.1 mg/dL', 'Within normal range.'), + (10, 2, 4, 'CBC (Complete Blood Count)', '2024-02-12', 'WBC: 6.5k/uL, Hemoglobin: 14 g/dL', 'Normal results.'), + (11, 2, 5, 'Liver Function Test', '2024-02-18', 'ALT: 30 U/L, AST: 28 U/L', 'Liver function normal.'), + + -- Reports for patient 3 (Sophia Martinez) + (12, 3, 2, 'Brain MRI', '2024-02-09', 'No lesions detected', 'Normal scan.'), + (13, 3, 4, 'Blood Pressure Test', '2024-02-14', '120/80 mmHg', 'Blood pressure normal.'), + (14, 3, 1, 'Glucose Tolerance Test', '2024-02-19', 'Fasting: 95 mg/dL, 2-hr: 140 mg/dL', 'Normal response.'), + + -- Reports for patient 4 (David Anderson) + (15, 4, 1, 'X-ray Chest', '2024-02-07', 'No abnormalities', 'Lungs are clear.'), + (16, 4, 5, 'Calcium Test', '2024-02-11', 'Calcium: 9.5 mg/dL', 'Within normal range.'), + (17, 4, 2, 'Thyroid Function Test', '2024-02-16', 'TSH: 2.5 uIU/mL', 'Thyroid function normal.'), + + -- Reports for patient 5 (Emma Harris) + (18, 5, 3, 'Allergy Panel', '2024-02-05', 'Mild pollen allergy', 'Avoid exposure to allergens.'), + (19, 5, 4, 'Urine Analysis', '2024-02-13', 'Normal pH and composition', 'No concerns.'), + (20, 5, 2, 'Iron Panel', '2024-02-17', 'Ferritin: 55 ng/mL', 'Iron levels within range.'), + + -- Reports for patient 6 (Daniel Thomas) + (21, 6, 5, 'Blood Sugar Test', '2024-02-06', 'Fasting: 100 mg/dL', 'Monitor periodically.'), + (22, 6, 1, 'Echocardiogram', '2024-02-10', 'Normal heart structure', 'No cardiac issues.'), + (23, 6, 2, 'Electrolyte Panel', '2024-02-14', 'Sodium: 140 mmol/L, Potassium: 4.0 mmol/L', 'Balanced electrolyte levels.'), + + -- Reports for patient 7 (Olivia White) + (24, 7, 3, 'Bone Density Test', '2024-02-07', 'T-score: -1.0', 'Mild osteopenia, calcium intake recommended.'), + (25, 7, 5, 'Lipid Profile', '2024-02-11', 'HDL: 50 mg/dL, LDL: 135 mg/dL', 'LDL slightly high, consider diet changes.'), + (26, 7, 4, 'Thyroid Ultrasound', '2024-02-15', 'No nodules detected', 'Thyroid appears normal.'); + + ``` + ![Execute Query](./images/insert-additional-labreports.png " ") + +6. Run the following command to validate that all the tables are created in the hospital database. + + ``` + SHOW TABLES; + ``` + ![Execute Query](./images/show-database.png " ") + +## Acknowledgements + +- Authors: Sindhuja Banka, MySQL HeatWave Product Manager +- Contributors: Sindhuja Banka, Farhan Tauheed +- Last Updated: Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/create-schema/images/appointments-table.png b/mysql-json-duality/create-schema/images/appointments-table.png new file mode 100644 index 000000000..941e15b52 Binary files /dev/null and b/mysql-json-duality/create-schema/images/appointments-table.png differ diff --git a/mysql-json-duality/create-schema/images/create-database.png b/mysql-json-duality/create-schema/images/create-database.png new file mode 100644 index 000000000..b58e5e13d Binary files /dev/null and b/mysql-json-duality/create-schema/images/create-database.png differ diff --git a/mysql-json-duality/create-schema/images/doctors-table.png b/mysql-json-duality/create-schema/images/doctors-table.png new file mode 100644 index 000000000..ba9e93f94 Binary files /dev/null and b/mysql-json-duality/create-schema/images/doctors-table.png differ diff --git a/mysql-json-duality/create-schema/images/insert-additional-labreports.png b/mysql-json-duality/create-schema/images/insert-additional-labreports.png new file mode 100644 index 000000000..2817dcbab Binary files /dev/null and b/mysql-json-duality/create-schema/images/insert-additional-labreports.png differ diff --git a/mysql-json-duality/create-schema/images/insert-appointments.png b/mysql-json-duality/create-schema/images/insert-appointments.png new file mode 100644 index 000000000..8e11cea82 Binary files /dev/null and b/mysql-json-duality/create-schema/images/insert-appointments.png differ diff --git a/mysql-json-duality/create-schema/images/insert-doctors.png b/mysql-json-duality/create-schema/images/insert-doctors.png new file mode 100644 index 000000000..8298624b3 Binary files /dev/null and b/mysql-json-duality/create-schema/images/insert-doctors.png differ diff --git a/mysql-json-duality/create-schema/images/insert-labreports.png b/mysql-json-duality/create-schema/images/insert-labreports.png new file mode 100644 index 000000000..c27664b11 Binary files /dev/null and b/mysql-json-duality/create-schema/images/insert-labreports.png differ diff --git a/mysql-json-duality/create-schema/images/insert-patients.png b/mysql-json-duality/create-schema/images/insert-patients.png new file mode 100644 index 000000000..e80342ee1 Binary files /dev/null and b/mysql-json-duality/create-schema/images/insert-patients.png differ diff --git a/mysql-json-duality/create-schema/images/labreports-table.png b/mysql-json-duality/create-schema/images/labreports-table.png new file mode 100644 index 000000000..0df273578 Binary files /dev/null and b/mysql-json-duality/create-schema/images/labreports-table.png differ diff --git a/mysql-json-duality/create-schema/images/patients-table.png b/mysql-json-duality/create-schema/images/patients-table.png new file mode 100644 index 000000000..adf1ed7b6 Binary files /dev/null and b/mysql-json-duality/create-schema/images/patients-table.png differ diff --git a/mysql-json-duality/create-schema/images/show-database.png b/mysql-json-duality/create-schema/images/show-database.png new file mode 100644 index 000000000..5cfc1fed4 Binary files /dev/null and b/mysql-json-duality/create-schema/images/show-database.png differ diff --git a/mysql-json-duality/create-schema/images/use-database.png b/mysql-json-duality/create-schema/images/use-database.png new file mode 100644 index 000000000..0ab68cfe0 Binary files /dev/null and b/mysql-json-duality/create-schema/images/use-database.png differ diff --git a/mysql-json-duality/ddl/ddl.md b/mysql-json-duality/ddl/ddl.md new file mode 100644 index 000000000..aa9ff20e7 --- /dev/null +++ b/mysql-json-duality/ddl/ddl.md @@ -0,0 +1,165 @@ +# Explore JSON Duality Views with MySQL + +## Introduction + +In this lab, you will learn how to create and use JSON Duality Views on a hospital database in MySQL HeatWave. JSON Duality Views allow you to work with your relational data as nested JSON objects making it easier to integrate with web and mobile applications. + +Estimated Lab Time: 15 minutes + +### Objectives + +In this lab, you will be guided through the following tasks: + +- Create a JSON Duality View from your hospital tables +- Query and view complex, nested JSON documents +- Understand the benefits of JSON Duality Views + +### Prerequisites + +- An Oracle Trial or Paid Cloud Account +- Some Experience with MySQL +- Completed Lab 4 + +## Task 1: Create a JSON Duality View + +1. Switch to your hospital database so you’re working in the right context. + + ``` + USE hospital; + ``` + ![Execute Query](./images/use-database.png " ") + +2. Let’s create a JSON Duality View called **patients_dv**. This view presents each patient as a JSON document, including all their appointments (with doctor details) and lab reports, all in a single nested JSON structure. + + ``` + + CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW patients_dv AS + SELECT JSON_DUALITY_OBJECT( + '_id': patient_id, + 'first_name': first_name, + 'last_name': last_name, + 'dob': dob, + 'gender': gender, + 'email': email, + 'appointments': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( + 'appointment_id': appointment_id, + 'appointment_time': appointment_time, + 'status': status, + 'notes': notes, + 'doctor': ( + SELECT JSON_DUALITY_OBJECT( + 'doctor_id': doctor_id, + 'first_name': first_name, + 'last_name': last_name, + 'specialty': specialty + ) + FROM doctors + WHERE doctors.doctor_id = appointments.doctor_id + ) + ) + ) + FROM appointments + WHERE patients.patient_id = appointments.patient_id + ), + 'reports': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( + 'report_id': report_id, + 'test_name': test_name, + 'test_date': test_date, + 'results': results, + 'remarks': remarks + )) + FROM lab_reports + WHERE lab_reports.patient_id = patients.patient_id + ) + ) + FROM patients; + + ``` + ![Execute Query](./images/create-jdv.png " ") + +3. This structure combines key information about a patient into an easily consumable JSON format, perfect for applications. + +## Task 2: Dive Deeper into the JSON + +1. You can look at the JSON generated for a specific patient and see all of their appointments and lab reports as nested objects. + + ``` + + SELECT JSON_PRETTY(data) FROM patients_dv WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/select-record.png " ") + +2. This makes it easy to send or consume patient data in modern applications without running multiple joins or additional queries. + +3. Here is the output of how it looks for patient 1. + + ![Execute Query](./images/patient1.png " ") + +## Task 3: (Optional) Create More Views as Needed + +1. You can create other versions of the view, or new views, to suit different application needs. For example, patients_dv_v2 might present the data slightly differently or include more information. + + ``` + + CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW patients_dv_v2 AS + SELECT JSON_DUALITY_OBJECT( + '_id': patient_id, + 'first_name': first_name, + 'last_name': last_name, + 'dob': dob, + 'gender': gender, + 'email': email, + 'appointments': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( + 'appointment_id': appointment_id, + 'appointment_time': appointment_time, + 'status': status, + 'notes': notes, + 'doctor': ( + SELECT JSON_DUALITY_OBJECT( + 'doctor_id': doctor_id, + 'first_name': first_name, + 'last_name': last_name, + 'specialty': specialty + ) + FROM doctors + WHERE doctors.doctor_id = appointments.doctor_id + ) + ) + ) + FROM appointments + WHERE patients.patient_id = appointments.patient_id + ), + 'reports': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( + 'report_id': report_id, + 'test_name': test_name, + 'test_date': test_date, + 'results': results, + 'remarks': remarks + )) + FROM lab_reports + WHERE lab_reports.patient_id = patients.patient_id + ) + ) + FROM patients; + + ``` + ![Execute Query](./images/create-jdv-2.png " ") + +2. This is how you can view both of your views created on the database connection panel. + + ![Execute Query](./images/views.png " ") + +## Acknowledgements + +- Authors: Sindhuja Banka, MySQL HeatWave Product Manager +- Contributors: Sindhuja Banka, Farhan Tauheed +- Last Updated: Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/ddl/images/create-jdv-2.png b/mysql-json-duality/ddl/images/create-jdv-2.png new file mode 100644 index 000000000..c941193a1 Binary files /dev/null and b/mysql-json-duality/ddl/images/create-jdv-2.png differ diff --git a/mysql-json-duality/ddl/images/create-jdv.png b/mysql-json-duality/ddl/images/create-jdv.png new file mode 100644 index 000000000..886c026e2 Binary files /dev/null and b/mysql-json-duality/ddl/images/create-jdv.png differ diff --git a/mysql-json-duality/ddl/images/patient1.png b/mysql-json-duality/ddl/images/patient1.png new file mode 100644 index 000000000..51859b025 Binary files /dev/null and b/mysql-json-duality/ddl/images/patient1.png differ diff --git a/mysql-json-duality/ddl/images/select-record.png b/mysql-json-duality/ddl/images/select-record.png new file mode 100644 index 000000000..89c85ab6d Binary files /dev/null and b/mysql-json-duality/ddl/images/select-record.png differ diff --git a/mysql-json-duality/ddl/images/use-database.png b/mysql-json-duality/ddl/images/use-database.png new file mode 100644 index 000000000..3d33a5c77 Binary files /dev/null and b/mysql-json-duality/ddl/images/use-database.png differ diff --git a/mysql-json-duality/ddl/images/views.png b/mysql-json-duality/ddl/images/views.png new file mode 100644 index 000000000..25105176d Binary files /dev/null and b/mysql-json-duality/ddl/images/views.png differ diff --git a/mysql-json-duality/dml/dml.md b/mysql-json-duality/dml/dml.md new file mode 100644 index 000000000..b04191308 --- /dev/null +++ b/mysql-json-duality/dml/dml.md @@ -0,0 +1,173 @@ +# Modify Data with JSON Relational Duality Views + +## Introduction + +This lab shows you how to use duality views to manage (insert, update, and delete) hospital data using JSON documents, while still enforcing relational integrity. You’ll see how modifications made via JSON documents are automatically reflected in your underlying relational tables. + +Estimated Lab Time: 15 minutes + +### Objectives + +In this lab, you will be guided through the following tasks: + +- Make duality views modifiable +- Insert JSON documents directly into duality views +- View data as JSON and as rows in base tables +- Control data changes and preserve integrity + +### Prerequisites + +- An Oracle Trial or Paid Cloud Account +- Some Experience with MySQL +- Completed Lab 5 + +## Task 1: Making Duality Views Modifiable + +1. Switch to your hospital database so you’re working in the right context. + + ``` + USE hospital; + ``` + ![Execute Query](./images/use-database.png " ") + +2. If you try to do an insert, update, or delete through this view now. + + ``` + + INSERT INTO hospital.patients_dv VALUES ( + '{ + "_id": 42, + "dob": "1985-06-15", + "last_name": "Tauheed", + "first_name": "Farhan", + "email": "farhan@example.com", + "gender": "Male", + "reports": [], + "appointments": [ + { + "notes": "Routine check-up", + "doctor": {"doctor_id": 1, "last_name": "Doe", "specialty": "Cardiology", "first_name": "John"}, + "status": "Scheduled", + "appointment_id": 42, + "appointment_time": "2024-02-05 10:00:00.000000" + } + ] + }'); + + ``` + ![Execute Query](./images/json-insert.png " ") + +3. You'll get an error because the view is read-only by default. + + ![Execute Query](./images/json-insert-error.png " ") + +4. To allow INSERT, UPDATE, or DELETE operations, you must specify modification tags WITH (INSERT, UPDATE, DELETE) in your view definition for each updatable object. + + ``` + + CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW patients_dv AS + SELECT JSON_DUALITY_OBJECT( WITH(INSERT,UPDATE,DELETE) + '_id': patient_id, + 'first_name': first_name, + 'last_name': last_name, + 'dob': dob, + 'gender': gender, + 'email': email, + 'appointments': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( WITH(INSERT,UPDATE,DELETE) + 'appointment_id': appointment_id, + 'appointment_time': appointment_time, + 'status': status, + 'notes': notes, + 'doctor': ( + SELECT JSON_DUALITY_OBJECT( + 'doctor_id': doctor_id, + 'first_name': first_name, + 'last_name': last_name, + 'specialty': specialty + ) + FROM doctors + WHERE doctors.doctor_id = appointments.doctor_id + ) + ) + ) + FROM appointments + WHERE patients.patient_id = appointments.patient_id + ), + 'reports': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( WITH(INSERT,UPDATE,DELETE) + 'report_id': report_id, + 'test_name': test_name, + 'test_date': test_date, + 'results': results, + 'remarks': remarks + ) + ) + FROM lab_reports + WHERE lab_reports.patient_id = patients.patient_id + ) + ) + FROM patients; + + ``` + ![Execute Query](./images/modified-jdv.png " ") + +5. Now, inserts, updates, and deletes are allowed on the views. + +6. This will create the patient, their appointment, and any reports (even if empty) in one step. + + ``` + + INSERT INTO patients_dv VALUES ( + '{ + "_id": 42, + "dob": "1985-06-15", + "last_name": "Wang", + "first_name": "Amy", + "email": "amy@example.com", + "gender": "Male", + "reports": [], + "appointments": [ + { + "notes": "Routine check-up", + "doctor": {"doctor_id": 1, "last_name": "Doe", "specialty": "Cardiology", "first_name": "John"}, + "status": "Scheduled", + "appointment_id": 42, + "appointment_time": "2024-02-05 10:00:00.000000" + } + ] + }'); + + ``` + ![Execute Query](./images/insert-new-record.png " ") + +7. You can query the Inserted JSON using the following command + + ``` + SELECT JSON_PRETTY(data) FROM patients_dv WHERE data->'$._id' = 42; + ``` + ![Execute Query](./images/select-new-record.png " ") + +8. Output is as follows. + ![Execute Query](./images/new-record-output.png " ") + +9. To remove the patient and all related child rows (appointments, reports), maintaining relational integrity, run the following command. + + ``` + DELETE FROM patients_dv WHERE data->'$._id' = 42; + ``` + ![Execute Query](./images/delete-record.png " ") + +9. To allow modifications (INSERT, UPDATE, DELETE) via duality views, always add WITH (INSERT, UPDATE, DELETE) in your JSON\_DUALITY\_OBJECTS. + +10. Modifying through duality views automatically keeps all related tables synchronized and enforces data integrity where your application can now work with your relational schema using just JSON! + + ![Execute Query](./images/show-patients-table.png " ") + +## Acknowledgements + +- Authors: Sindhuja Banka, MySQL HeatWave Product Manager +- Contributors: Sindhuja Banka, Farhan Tauheed +- Last Updated: Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/dml/images/delete-record.png b/mysql-json-duality/dml/images/delete-record.png new file mode 100644 index 000000000..fb1afe2ae Binary files /dev/null and b/mysql-json-duality/dml/images/delete-record.png differ diff --git a/mysql-json-duality/dml/images/insert-new-record.png b/mysql-json-duality/dml/images/insert-new-record.png new file mode 100644 index 000000000..5d844db44 Binary files /dev/null and b/mysql-json-duality/dml/images/insert-new-record.png differ diff --git a/mysql-json-duality/dml/images/json-insert-error.png b/mysql-json-duality/dml/images/json-insert-error.png new file mode 100644 index 000000000..80a86fd2a Binary files /dev/null and b/mysql-json-duality/dml/images/json-insert-error.png differ diff --git a/mysql-json-duality/dml/images/json-insert.png b/mysql-json-duality/dml/images/json-insert.png new file mode 100644 index 000000000..085f16c1e Binary files /dev/null and b/mysql-json-duality/dml/images/json-insert.png differ diff --git a/mysql-json-duality/dml/images/modified-jdv.png b/mysql-json-duality/dml/images/modified-jdv.png new file mode 100644 index 000000000..b72f52adc Binary files /dev/null and b/mysql-json-duality/dml/images/modified-jdv.png differ diff --git a/mysql-json-duality/dml/images/new-record-output.png b/mysql-json-duality/dml/images/new-record-output.png new file mode 100644 index 000000000..2be22c33b Binary files /dev/null and b/mysql-json-duality/dml/images/new-record-output.png differ diff --git a/mysql-json-duality/dml/images/select-new-record.png b/mysql-json-duality/dml/images/select-new-record.png new file mode 100644 index 000000000..16eb07147 Binary files /dev/null and b/mysql-json-duality/dml/images/select-new-record.png differ diff --git a/mysql-json-duality/dml/images/show-patients-table.png b/mysql-json-duality/dml/images/show-patients-table.png new file mode 100644 index 000000000..a4f5f0727 Binary files /dev/null and b/mysql-json-duality/dml/images/show-patients-table.png differ diff --git a/mysql-json-duality/dml/images/use-database.png b/mysql-json-duality/dml/images/use-database.png new file mode 100644 index 000000000..3d33a5c77 Binary files /dev/null and b/mysql-json-duality/dml/images/use-database.png differ diff --git a/mysql-json-duality/introduction/images/mysql-ai-chatbot-rag.png b/mysql-json-duality/introduction/images/mysql-ai-chatbot-rag.png new file mode 100644 index 000000000..6ddc1df34 Binary files /dev/null and b/mysql-json-duality/introduction/images/mysql-ai-chatbot-rag.png differ diff --git a/mysql-json-duality/introduction/images/rag-diagram-pipe.png b/mysql-json-duality/introduction/images/rag-diagram-pipe.png new file mode 100644 index 000000000..827e0b85c Binary files /dev/null and b/mysql-json-duality/introduction/images/rag-diagram-pipe.png differ diff --git a/mysql-json-duality/introduction/images/rag-diagram.png b/mysql-json-duality/introduction/images/rag-diagram.png new file mode 100644 index 000000000..983f2ee97 Binary files /dev/null and b/mysql-json-duality/introduction/images/rag-diagram.png differ diff --git a/mysql-json-duality/introduction/introduction.md b/mysql-json-duality/introduction/introduction.md new file mode 100644 index 000000000..42975be4d --- /dev/null +++ b/mysql-json-duality/introduction/introduction.md @@ -0,0 +1,44 @@ +# Introduction + +## About this Workshop + +Modern applications often need to work with both document-centric JSON and traditional relational data. JSON Relational Duality Views introduce a new way to unify these models where you can seamlessly read and write hierarchical JSON documents mapped directly to normalized relational tables, gaining both development agility and robust data integrity. This feature is available in MySQL HeatWave, MySQL Enterprise Edition, and in read-only mode in MySQL Community Edition. + +In this workshop, you will use JSON Duality Views enabling you to seamlessly integrate the flexibility of hierarchical JSON documents with the reliability and efficiency of relational database structures. + +By leveraging JSON Duality Views, you get the best of both worlds: + +- The query and integrity strengths of traditional relational models +- The flexible, modern data exchange patterns of the JSON model + +### Objectives + +JSON Duality Views allow you to define and store queries that present relational data as virtual JSON documents. With this feature, you can map complex relationships and tables into easily consumable multi-level JSON structures perfect for modern applications and REST APIs that require both structured and semi-structured data access. + +In this workshop, you will learn: + +- Exploring JSON Duality Views with MySQL +- Perform insert, update and delete operations against JSON Duality Views +- Modifying data with JSON Relational Duality Views +- Optimistic Concurrency Control with JSON Duality Views + +Estimated Workshop Time: 90 minutes + +## Prerequisites + +In order to do this workshop, you'll need: + +- Oracle Free Tier or paid Cloud account +- Basic SQL knowledge + +## Learn More + +- [Introducing JSON Relational Duality Views in MySQL HeatWave](https://blogs.oracle.com/mysql/post/two-models-one-world-introducing-json-relational-duality-views-in-mysql-heatwave) +- [JSON Duality Views Documentation](https://dev.mysql.com/doc/refman/9.4/en/json-duality-views.html) +- [MySQL HeatWave](https://dev.mysql.com/doc/) + +## Acknowledgements + +- **Authors:** Sindhuja Banka, MySQL HeatWave Product Manager +- **Contributors:** Sindhuja Banka, Farhan Tauheed +- **Last Updated:** Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/occ/images/doctor-new-etag.png b/mysql-json-duality/occ/images/doctor-new-etag.png new file mode 100644 index 000000000..f98dbc5cc Binary files /dev/null and b/mysql-json-duality/occ/images/doctor-new-etag.png differ diff --git a/mysql-json-duality/occ/images/doctor-query-output.png b/mysql-json-duality/occ/images/doctor-query-output.png new file mode 100644 index 000000000..10566e331 Binary files /dev/null and b/mysql-json-duality/occ/images/doctor-query-output.png differ diff --git a/mysql-json-duality/occ/images/doctor-update-etag.png b/mysql-json-duality/occ/images/doctor-update-etag.png new file mode 100644 index 000000000..af8fab6b2 Binary files /dev/null and b/mysql-json-duality/occ/images/doctor-update-etag.png differ diff --git a/mysql-json-duality/occ/images/doctors-jdv.png b/mysql-json-duality/occ/images/doctors-jdv.png new file mode 100644 index 000000000..5c17b94fb Binary files /dev/null and b/mysql-json-duality/occ/images/doctors-jdv.png differ diff --git a/mysql-json-duality/occ/images/error-etag.png b/mysql-json-duality/occ/images/error-etag.png new file mode 100644 index 000000000..3edb407af Binary files /dev/null and b/mysql-json-duality/occ/images/error-etag.png differ diff --git a/mysql-json-duality/occ/images/execute-doctor-query.png b/mysql-json-duality/occ/images/execute-doctor-query.png new file mode 100644 index 000000000..83a5c0d07 Binary files /dev/null and b/mysql-json-duality/occ/images/execute-doctor-query.png differ diff --git a/mysql-json-duality/occ/images/execute-query.png b/mysql-json-duality/occ/images/execute-query.png new file mode 100644 index 000000000..fff0d763b Binary files /dev/null and b/mysql-json-duality/occ/images/execute-query.png differ diff --git a/mysql-json-duality/occ/images/patient-update-etag.png b/mysql-json-duality/occ/images/patient-update-etag.png new file mode 100644 index 000000000..9d53547a0 Binary files /dev/null and b/mysql-json-duality/occ/images/patient-update-etag.png differ diff --git a/mysql-json-duality/occ/images/query-output.png b/mysql-json-duality/occ/images/query-output.png new file mode 100644 index 000000000..340a9aaec Binary files /dev/null and b/mysql-json-duality/occ/images/query-output.png differ diff --git a/mysql-json-duality/occ/images/re-read-doctor-etag.png b/mysql-json-duality/occ/images/re-read-doctor-etag.png new file mode 100644 index 000000000..2d0c2407e Binary files /dev/null and b/mysql-json-duality/occ/images/re-read-doctor-etag.png differ diff --git a/mysql-json-duality/occ/images/run-jdv.png b/mysql-json-duality/occ/images/run-jdv.png new file mode 100644 index 000000000..dad06a300 Binary files /dev/null and b/mysql-json-duality/occ/images/run-jdv.png differ diff --git a/mysql-json-duality/occ/images/select-doctors.png b/mysql-json-duality/occ/images/select-doctors.png new file mode 100644 index 000000000..c99cac19f Binary files /dev/null and b/mysql-json-duality/occ/images/select-doctors.png differ diff --git a/mysql-json-duality/occ/images/use-database.png b/mysql-json-duality/occ/images/use-database.png new file mode 100644 index 000000000..3d33a5c77 Binary files /dev/null and b/mysql-json-duality/occ/images/use-database.png differ diff --git a/mysql-json-duality/occ/occ.md b/mysql-json-duality/occ/occ.md new file mode 100644 index 000000000..bee976ab3 --- /dev/null +++ b/mysql-json-duality/occ/occ.md @@ -0,0 +1,334 @@ +# Optimistic Concurrency Control with JSON Duality Views + +## Introduction + +This lab shows you how when two users (like a patient and a doctor) try to update the same appointment at almost the same time from different apps, it’s possible for one user's changes to overwrite the other's. Optimistic Concurrency Control (OCC) avoids this risk by using an ETAG which is a special value that changes every time data is updated so that the updates only succeed if the data hasn't changed since it was read. + +Estimated Lab Time: 15 minutes + +### Objectives + +In this lab, you will be guided through the following tasks: + +- Make duality views modifiable +- Insert JSON documents directly into duality views +- View data as JSON and as rows in base tables +- Control data changes and preserve integrity + +### Prerequisites + +- An Oracle Trial or Paid Cloud Account +- Some Experience with MySQL +- Completed Lab 6 + +## Task 1: Setup Duality Views + +1. Switch to your hospital database so you’re working in the right context. + + ``` + USE hospital; + ``` + ![Execute Query](./images/use-database.png " ") + +2. We already have a view exposes patient records as JSON. Specifying WITH (INSERT, UPDATE, DELETE) allows you to insert, update, or delete patient records as JSON documents. Nested (child) tables such as appointments and lab reports are also included and can be modified directly from the JSON structure. + + ``` + + CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW patients_dv AS + SELECT JSON_DUALITY_OBJECT( WITH (INSERT, UPDATE, DELETE) + '_id': patient_id, + 'first_name': first_name, + 'last_name': last_name, + 'dob': dob, + 'gender': gender, + 'email': email, + 'appointments': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( WITH (INSERT, UPDATE, DELETE) + 'appointment_id': appointment_id, + 'appointment_time': appointment_time, + 'status': status, + 'notes': notes, + 'doctor': ( + SELECT JSON_DUALITY_OBJECT( WITH (INSERT, UPDATE) + 'doctor_id': doctor_id, + 'first_name': first_name, + 'last_name': last_name, + 'specialty': specialty + ) + FROM doctors + WHERE coctors.doctor_id = appointments.doctor_id + ) + ) + ) + FROM appointments + WHERE patients.patient_id = appointments.patient_id + ), + 'reports': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( WITH (INSERT, UPDATE, DELETE) + 'report_id': report_id, + 'test_name': test_name, + 'test_date': test_date, + 'results': results, + 'remarks': remarks + )) + FROM lab_reports + WHERE lab_reports.patient_id = patients.patient_id + ) + ) + FROM patients; + + ``` + ![Execute Query](./images/run-jdv.png " ") + +2. A client (such as a web or mobile app) retrieves the patient record from the duality view as a JSON document. This includes ETAG metadata needed for concurrency control. + + ``` + + SELECT JSON_PRETTY(data) FROM patients_dv WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/execute-query.png " ") + +3. Output is as follows. + ![Execute Query](./images/query-output.png " ") + +4. The record is formatted nicely as JSON for the application. The ETAG value is included, acting as a “version” so later updates can safely check for conflicts. + +5. You also have a view that exposes doctor records as JSON. It also lists their appointments, and each appointment includes linked patient information. Making the appointments JSON object modifiable enables direct updates from the doctor’s perspective. + + ``` + + CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW doctors_dv AS + SELECT JSON_DUALITY_OBJECT( + '_id': doctor_id, + 'first_name': first_name, + 'last_name': last_name, + 'specialty': specialty, + 'department': department, + 'email': email, + 'appointments': ( + SELECT JSON_ARRAYAGG( + JSON_DUALITY_OBJECT( WITH (INSERT, UPDATE, DELETE) + 'appointment_id': appointment_id, + 'appointment_time': appointment_time, + 'status': status, + 'notes': notes, + 'patient': ( + SELECT JSON_DUALITY_OBJECT( + 'patient_id': patient_id, + 'first_name': first_name, + 'last_name': last_name, + 'email': email + ) + FROM patients + WHERE patients.patient_id = appointments.patient_id + ) + ) + ) + FROM appointments + WHERE doctors.doctor_id = appointments.doctor_id + ) + ) + FROM doctors; + + ``` + ![Execute Query](./images/doctors-jdv.png " ") + +6. A client for the doctor (web or mobile) fetches the doctor’s details and all related appointments as a JSON document. Again, ETAG is included for concurrency control. + + ``` + + SELECT JSON_PRETTY(data) FROM doctors_dv WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/select-doctors.png " ") + +3. Output is as follows. + ![Execute Query](./images/doctor-query-output.png " ") + +7. Doctor can see their complete schedule and appointment information as a structured JSON. The ETAG helps ensure updates don’t overwrite each other. + +8. A single appointment row appears in both the patient and doctor views because it is linked by foreign keys (relational integrity), and both users may attempt to update it from their respective views. + +9. The patient’s app updates the JSON with new appointment information. The ETAG from the most recent read is included in the update WHERE clause. This way, the update only succeeds if the data has not changed since last read. + + ``` + + UPDATE patients_dv + SET data = '{ + "_id": 1, + "dob": "1985-06-15", + "email": "alicejohnson@example.com", + "gender": "Female", + "reports": [ + { + "remarks": "Slightly elevated, monitor regularly", + "results": "Fasting: 110 mg/dL, Post-meal: 140 mg/dL", + "report_id": 1, + "test_date": "2024-02-01", + "test_name": "Blood Sugar Test" + }, + { + "remarks": "Normal levels, maintain diet.", + "results": "Total: 200 mg/dL, LDL: 120 mg/dL", + "report_id": 6, + "test_date": "2024-02-10", + "test_name": "Cholesterol Test" + }, + { + "remarks": "Healthy heart rhythm.", + "results": "No abnormalities detected", + "report_id": 7, + "test_date": "2024-02-15", + "test_name": "ECG" + }, + { + "remarks": "Slightly low, consider supplements.", + "results": "Vitamin D: 22 ng/mL", + "report_id": 8, + "test_date": "2024-02-20", + "test_name": "Vitamin D Test" + } + ], + "_metadata": { + "etag": "b2803e8ec2c8144dc47ffbb677b4284d" + }, + "last_name": "Johnson", + "first_name": "Alice", + "appointments": [ + { + "notes": "Routine check-up", + "doctor": { + "doctor_id": 1, + "last_name": "Doe", + "specialty": "Cardiology", + "first_name": "John" + }, + "status": "Scheduled", + "appointment_id": 1, + "appointment_time": "2024-02-12 10:00:00.000000" + } + ] + }' + WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/patient-update-etag.png " ") + +10. If the ETAG matches what’s in the database, the update goes through. If not, someone else has made a change; the update fails to protect data integrity. + +11. If the doctor, working with old data (including a stale ETAG), attempts to update the appointment, the database compares ETAGs. + + ``` + + UPDATE doctors_dv + SET data = '{ + "_id": 1, + "email": "johndoe@example.com", + "_metadata": { + "etag": "970d69c5550f6bfffc35b99e9efc877c" + }, + "last_name": "Doe", + "specialty": "Cardiology", + "department": "Cardiology", + "first_name": "John", + "appointments": [ + { + "notes": "Routine check-up", + "status": "Scheduled", + "patient": { + "email": "alicejohnson@example.com", + "last_name": "Johnson", + "first_name": "Alice", + "patient_id": 1 + }, + "appointment_id": 1, + "appointment_time": "2024-02-08 10:00:00.000000" + }, + { + "notes": "Heart condition follow-up", + "status": "Scheduled", + "patient": { + "email": "danielthomas@example.com", + "last_name": "Thomas", + "first_name": "Daniel", + "patient_id": 6 + }, + "appointment_id": 6, + "appointment_time": "2024-02-10 12:00:00.000000" + } + ] + }' + WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/doctor-update-etag.png " ") + +12. If the appointment was already changed by the patient (and ETAG updated), this doctor’s update is blocked. The doctor must reload current data, get the new ETAG, and then try again. + + ![Execute Query](./images/error-etag.png " ") + +13. ETAG is a hidden version column that tracks changes. Every update to the record causes ETAG to change. OCC ensures only one user’s update succeeds unless they both work from the most up-to-date version. + +14. So, if your app gets a concurrency error, simply: + +- Re-read the data and get the current ETAG +- Merge your intended changes +- Try the update again + + ![Execute Query](./images/re-read-doctor-etag.png " ") + + ``` + + UPDATE doctors_dv + SET data = '{ + "_id": 1, + "email": "johndoe@example.com", + "_metadata": { + "etag": "8beb00003a96e59351c782f74ab7ca5e" + }, + "last_name": "Doe", + "specialty": "Cardiology", + "department": "Cardiology", + "first_name": "John", + "appointments": [ + { + "notes": "Routine check-up", + "status": "Scheduled", + "patient": { + "email": "alicejohnson@example.com", + "last_name": "Johnson", + "first_name": "Alice", + "patient_id": 1 + }, + "appointment_id": 1, + "appointment_time": "2024-02-12 10:00:00.000000" + }, + { + "notes": "Heart condition follow-up", + "status": "Scheduled", + "patient": { + "email": "danielthomas@example.com", + "last_name": "Thomas", + "first_name": "Daniel", + "patient_id": 6 + }, + "appointment_id": 6, + "appointment_time": "2024-02-10 12:00:00.000000" + } + ] + }' + WHERE data->'$._id' = 1; + + ``` + ![Execute Query](./images/doctor-new-etag.png " ") + + ![Execute Query](./images/execute-doctor-query.png " ") + +## Acknowledgements + +- Authors: Sindhuja Banka, MySQL HeatWave Product Manager +- Contributors: Sindhuja Banka, Farhan Tauheed +- Last Updated: Sindhuja Banka, November 2025 diff --git a/mysql-json-duality/workshops/index.html b/mysql-json-duality/workshops/index.html new file mode 100644 index 000000000..b197fc302 --- /dev/null +++ b/mysql-json-duality/workshops/index.html @@ -0,0 +1,62 @@ + + + + + + + + + Oracle LiveLabs + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+ + + + diff --git a/mysql-json-duality/workshops/manifest.json b/mysql-json-duality/workshops/manifest.json new file mode 100644 index 000000000..d00156e0a --- /dev/null +++ b/mysql-json-duality/workshops/manifest.json @@ -0,0 +1,63 @@ +{ + "workshoptitle": "Two Models, One World: JSON Relational Duality Views in MySQL HeatWave", + "help": "livelabs-help-oci_us@oracle.com", + "tutorials": [ + { + "title": "Introduction", + "description": "The Introduction is always second. The title and contents menu title match for the Introduction.", + "filename": "../introduction/introduction.md" + }, + + { + "title": "Get Started", + "description": "Prerequisites for LiveLabs (Oracle-owned tenancies). The title of the lab and the Contents Menu title (the title above) match for Prerequisite lab. This lab is always first.", + "filename": "https://oracle-livelabs.github.io/common/labs/cloud-login/pre-register-free-tier-account.md" + }, + + { + "title": "Lab 1: Create SSH keys using Oracle Cloud Shell", + "description": "The Introduction is always second. The title and contents menu title match for the Introduction.", + "filename": "https://oracle-livelabs.github.io/common/labs/generate-ssh-key-cloud-shell/generate-ssh-keys-cloud-shell.md" + }, + + { + "title": "Lab 2: Create MySQL HeatWave DB system", + "filename": "../create-mysql-heatwave/mysql-heatwave.md" + }, + + { + + "title": "Lab 3: Connect to MySQL HeatWave DB system", + "filename": "../connect-mysql-heatwave/connect-mysql-heatwave.md" + }, + + { + + "title": "Lab 4: Create schema and relational tables ", + "filename": "../create-schema/create-schema.md" + }, + + { + + "title": "Lab 5: Explore JSON Duality Views with MySQL ", + "filename": "../ddl/ddl.md" + }, + + { + + "title": "Lab 6: Modify Data with JSON Relational Duality Views ", + "filename": "../dml/dml.md" + }, + + { + + "title": "Lab 7: Optimistic Concurrency Control with JSON Duality Views", + "filename": "../occ/occ.md" + }, + + { + "title": "Need Help?", + "description": "Solutions to Common Problems and Directions for Receiving Live Help", + "filename":"https://oracle-livelabs.github.io/common//labs/need-help/need-help-freetier.md"} + ] +}