create SQL to join a fact table key based on "join_col" to a dimension 
        The fact table is aliased as "op" and the join dimension is aliased as "ip"
        meaning you can pass substrings or SQL to match values.
        e.g. the command:
        aup.key_to_dimension('GENDER_KEY', 'substr(op.GENDER, 1,1)', 'tbl_GENDER', 'gender_code', 'GENDER_KEY')

        will generate the code:
        UPDATE table op SET op.gender_key = NVL ( (SELECT MAX (ip.gender_key)
          FROM tbl_GENDER ip WHERE ip.gender_code = SUBSTR (op.gender, 1, 1)), -1);

def key_to_dimension(self, fact_key, fact_join_col, dimension_name, dimension_join_col, dimension_key):
        """ 
        create SQL to join a fact table key based on "join_col" to a dimension 
        The fact table is aliased as "op" and the join dimension is aliased as "ip"
        meaning you can pass substrings or SQL to match values.
        e.g. the command:
        aup.key_to_dimension('GENDER_KEY', 'substr(op.GENDER, 1,1)', 'tbl_GENDER', 'gender_code', 'GENDER_KEY')

        will generate the code:
        UPDATE table op SET op.gender_key = NVL ( (SELECT MAX (ip.gender_key)
          FROM tbl_GENDER ip WHERE ip.gender_code = SUBSTR (op.gender, 1, 1)), -1);
        """
        
        self.sql_text += "UPDATE " + self.fact_table + " op SET op." + fact_key + " = NVL(\n"
        self.sql_text += "  (SELECT MAX (ip." + dimension_key + ")\n"
        self.sql_text += "    FROM " + dimension_name + " ip WHERE "
        self.sql_text += fact_join_col + " = \n       ip." + dimension_join_col + "), -1); \n\n"