Skip to main content


Searching for multiple words

I Imagine a table with products. For simplicity lets use just product name and description. CREATE TABLE products ( product_id NUMBER(10), product_name VARCHAR2(256), product_desc VARCHAR2(4000), -- CONSTRAINT pk_products PRIMARY KEY (product_id) ); -- DELETE FROM products; INSERT INTO products SELECT 1, 'First product name, one', 'Some description' FROM DUAL UNION ALL SELECT 2, 'Second product name, two', 'Another description' FROM DUAL UNION ALL SELECT 3, 'Third product, three', 'Other description' FROM DUAL; -- COMMIT; How would you search for a product with specific words in name and description? If you want to search for products containing 'First' OR 'one' words in name, then it is quite easy (case search and sanitization of inputs not included). WITH input AS ( SELECT /*+ MATERIALIZE */ 'First:one' AS in_name,
Recent posts

On checking input values

U Usually I see (and do) evaluations at the start of the procedure. When you check for multiple things, it can get lengthy and the reusability of the code is very low. Does this look familiar? DECLARE in_user_id CONSTANT VARCHAR2(30) := 'USER_NAME'; BEGIN -- check inputs IF in_user_id IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'USER_ID_MANDATORY'); END IF; -- IF LENGTH(in_user_id) < 3 THEN RAISE_APPLICATION_ERROR(-20000, 'USER_ID_MIN_LENGTH'); END IF; -- IF NOT REGEXP_LIKE(in_user_id, '@') THEN RAISE_APPLICATION_ERROR(-20000, 'USER_ID_FAILED'); END IF; -- continue with your code NULL; END; / Imagine this instead: DECLARE in_user_id CONSTANT VARCHAR2(30) := 'USER_NAME'; BEGIN -- check inputs assert.is_not_null('USER_ID_MANDATORY', in_user_id); assert.is_false('USER_ID_MIN_LENGTH', LENGTH(in_user_id) &

APEX & Stripe payment gateway (demo app)

I I have been ask to implement Stripe payments into APEX. I see two options here. You can either do it in JavaScript or in PL/SQL. You can easily call a web service from PL/SQL, you wont need any extra JS library and code would be probably more secured. So let's do that. You can find several other articles about this around. If you saw those, you can evaluate yourself on how is this different. The easiest API choice on almost every payment gateway is called "checkout" or "checkout form". The beauty about this is that there are no sensitive data processed on your side, everything is processed on the payment gateway side. No worries about storing or processing client cards. You should check the Stripe Checkout and specially Quickstart . Stripe (and others) like to show the user a list of products with quantities and prices during the checkout. Hence you need to create products on Stripe and you have to do that everytime you add (or change) a new produc

APEX Tabs with Badges

D Did you ever wanted to add badges to the tab names in Tabs component ? You might expect this will be simple. But it is not. You add a <span> to the name and your tabs will break (see the image below). Expected result is on the right. So what you need to do? assign TABS static id to your Tabs region assign any static id to all your tabs (subregions) create page item for each tab fill these items however you like create DA to add these badges after the tabs are created adjust CSS styles to your needs Here is the DA which will map your badge items to the proper tabs. So on page 1 it will map P1_ TAB_A _BADGE item to the TAB_A tab (subregion with TAB_A static id). setTimeout(function() { var tabs_id = 'TABS'; // static_id for the Tabs region var badges = '_BADGE'; // postfix for badge items // if (!$('#' + tabs_id)) { return; } var tabs = apex.regio

Adding/dropping columns in a repeatable way

O On one of my projects I have to create patch scripts to add columns to a table or remove them. Thing is, that they might be run multiple times or might get different result on different environments. So I created this simple script where I can define which column in which table I need to add or drop and it will skip what was already done. Keep in mind that I am not solving changed data types nor the column positions. PROMPT PROCESSING TABLE CHANGES -- SET SERVEROUTPUT ON BEGIN FOR c IN ( WITH x (action, table_name, column_name, data_type) AS ( SELECT 'ADD', 'TABLE_NAME', 'COLUMN_NAME1', 'NUMBER' FROM DUAL UNION ALL SELECT 'DROP', 'TABLE_NAME', 'COLUMN_NAME2', NULL FROM DUAL ) SELECT x.*, c.column_name AS column_exists FROM x LEFT JOIN user_tab_cols c ON c.table_name = x.table_name AND c.column_name = x.column_name ) LOOP

Sharpen the saw

I Imagine this. You know stuff. Maybe a lot of stuff. How long does this last if you don't add new skills and new experience regularly? How long before you are being replaced by someone else or worst something else? How easily will you get a new job? How can you provide high quality services to your clients? I have met a lot of APEX developers. Many of them on senior level, doing APEX for 10+ years. But many of them also stuck on APEX 5 and Oracle 11g, rarely 12c. Do you realize that 11g is like 15 years old and APEX 5 half of that? You really can't call yourself a senior if you are doing the same thing for 10 years, can you? Do you know how many of these guys know at least one new feature from latest APEX? Or a main difference between 11g and 12c? Zero. One new feature from 19c? Zero. I also see this over and over in teams: We don't have time to refactor the code. We will do that in phase two (never). We don't have time to write unit tests.

Set page items based on SQL query

I If you want to create a lot of items on APEX page, you should use the Form region. Based on a table/view or query it will create items for every column and add init process to prefill these items for you when you pass a primary key. Neat. The thing is, sometimes I can't use the form processes, I just need to set items based on a query. The usual approach is to SELECT INTO (select columns into the items). For 20 items you will get 40+ lines query, for 60 items you will get 120+ lines, you get the idea. You have to be careful about the column names and items names and not to mix them. And this also leads to different item names than columns. SELECT column_name1, column_name2, column_name3, column_name4 ... INTO :P100_column_name1, :P100_column_nameee2, :P100_column_name3, :P100_col_name4 ... FROM your_table WHERE ROWNUM = 1; How about this? DECLARE l_curs SYS_REFCURSOR; BEGIN OPEN l_curs FOR SELECT * -- your columns whi

Oracle ACE Associate

T This week I got my Oracle ACE Associate award. I feel very excited, honoured and proud to receive this recognition. Not everyone can get it. It is certainly the best work related event for me in years. There are currently 392 ACEs world wide, 196 in Database focus area, 99 in EMEA region and just me in Czech Republic. My interested at Oracle started when I was a kid and I bought a book about Oracle 7i. I didn't understand it and it was very hard to even install the database then. I started developing web applications as a freelancer when I was 18 and could legally set up my first company. PHP cluttered with MySQL calls was my first choice. But I was lured by Oracle's ability to store and execute the business logic inside of the database and to even run the webserver there. Magic. So I found a job at StringData where I had the opportunity to learn Oracle on commercial projects. I grew up on the Oracle Base blog from Tim Hall , on orange books from Steven Feuerstein ,

Comparing tables in the same schema

R Recently I have encountered a strange data model. Imagine you have an app with many tables for a specific group of users. Then you are asked to add a second group of users to the app. These groups have same tables but must not see records from the other group. Author of this solution decided to copy all objects (not just tables) and use a different prefix for them. Then he made some small adjustments here and there. For tables, views, mviews, triggers and packages. He skipped sequences for some reason. If you wonder why is this strange, then think about how would you proceed if you have been asked to add a third, fourth or fifth group of users... The issue I have was how can I quickly compare these tables to analyze how much they overlap? They are in the same scheme and they have different prefixes. I don't want to compare them one by one manually. Here is the script I wrote for this, just change the prefixes: WITH x AS ( SELECT /*+ MATERIALIZE */ 'P1_&

Find where are the authorization schemes used

I I was tired of searching the app for places where is the authorization scheme referenced. So I wrote this script to get a nice overview of components and relevant pages. To get list of the autorization schemes/roles: SELECT a.authorization_scheme_name AS scheme_name, a.authorization_scheme_id AS scheme_id FROM apex_application_authorization a WHERE a.application_id = &APP_ID ORDER BY 1; To get list of components and relevant pages: SET SERVEROUTPUT ON DECLARE in_app_id CONSTANT NUMBER := &APP_ID; -- v_records NUMBER; v_pages VARCHAR2(4000); BEGIN FOR c IN ( WITH x AS ( SELECT a.application_id, a.authorization_scheme_name AS scheme_name, a.authorization_scheme_id AS scheme_id FROM apex_application_authorization a WHERE a.application_id = in_app_id ), p AS ( SELECT d.apex_view_n