deb
deb

Reputation: 425

Oracle Table design question: configuration table, default values, primary keys

need to design a table in Oracle, these are my columns:

  1. COUNTRY
  2. PRODUCT
  3. PARAM1
  4. PARAM2
  5. PARAM3

My first thought was that I would like the combination of Country and Product to be a PK. But then, I also want a catch-all/Default for anything that doesn't fall into the records for Country + Product. Example:

Looks like I should let Product and Country be nullable and not a PK, but I wonder if I'm missing any other options.

Any thoughts would be greatly appreciated.

Cheers!

Upvotes: 0

Views: 34

Answers (1)

Radagast81
Radagast81

Reputation: 3016

One possibility is the use of virtual columns:

CREATE TABLE country_parms
    (country                        VARCHAR2(50 CHAR),
    product                        VARCHAR2(50 CHAR),
    param1                         VARCHAR2(50 CHAR),
    param2                         VARCHAR2(50 CHAR),
    param3                         VARCHAR2(50 CHAR),
    country_nn                     VARCHAR2(50 CHAR) GENERATED ALWAYS AS (NVL("COUNTRY",'-')) ,
    product_nn                     VARCHAR2(50 CHAR) GENERATED ALWAYS AS (NVL("PRODUCT",'-')) ,
    PRIMARY KEY  (country_nn, product_nn)
    )

With this approach you can also use fk-constraints to your country and product table. To select the values you use a view like the following:

SELECT c.country
     , p.product
     , CASE WHEN cp1.country_nn IS NOT NULL THEN cp1.param1
            WHEN cp2.country_nn IS NOT NULL THEN cp2.param1
            WHEN cp3.country_nn IS NOT NULL THEN cp3.param1
            ELSE cp4.param1
       END param1
     , CASE WHEN cp1.country_nn IS NOT NULL THEN cp1.param2
            WHEN cp2.country_nn IS NOT NULL THEN cp2.param2
            WHEN cp3.country_nn IS NOT NULL THEN cp3.param2
            ELSE cp4.param2
       END param2
     , CASE WHEN cp1.country_nn IS NOT NULL THEN cp1.param3
            WHEN cp2.country_nn IS NOT NULL THEN cp2.param3
            WHEN cp3.country_nn IS NOT NULL THEN cp3.param3
            ELSE cp4.param3
       END param3
  FROM country c
 CROSS JOIN product p
  LEFT JOIN country_parms cp1
    ON cp1.country_nn = c.country
   AND cp1.product_nn = p.product
  LEFT JOIN country_parms cp2
    ON cp2.country_nn = c.country
   AND cp2.product_nn = '-'
  LEFT JOIN country_parms cp3
    ON cp3.country_nn = '-'
   AND cp3.product_nn = p.product
  LEFT JOIN country_parms cp4
    ON cp4.country_nn = '-'
   AND cp4.product_nn = '-'

Using the cross product of all countries and products and then first look for the exact fit, then the one where product is empty, then where country is empty and finally where both are empty to get the config of the parameters.

Or even simplier:

  SELECT MAX(param1) KEEP (DENSE_RANK FIRST ORDER BY country nulls last
                                                   , product nulls last) param1
       , MAX(param2) KEEP (DENSE_RANK FIRST ORDER BY country nulls last
                                                   , product nulls last) param2
       , MAX(param3) KEEP (DENSE_RANK FIRST ORDER BY country nulls last
                                                   , product nulls last) param3                                              
    FROM country_parms
   WHERE country_nn IN (:country_nn, '-')
     AND product_nn IN (:product_nn, '-')

Upvotes: 1

Related Questions