Formatted Input in Table in plsql - sql

I want to input the following things -
ACCEPT p_cname PROMPT 'Enter Customer Name: '
ACCEPT p_cyear PROMPT 'Enter Car Year: '
ACCEPT p_color PROMPT 'Enter Car Color: '
ACCEPT p_make PROMPT 'Enter Car Make: '
ACCEPT p_model PROMPT 'Enter Car Model: '
ACCEPT p_trim PROMPT 'Enter Car Trim: '
ACCEPT p_enginetype PROMPT 'Enter Car Engine Type: '
ACCEPT p_option PROMPT 'Enter Option Name: '
ACCEPT p_ocode PROMPT 'Enter Option Code: '
then add it in table as
NAME - WANT
Name - year color model trim enginetype 'w/' Option ( ocode )
I tried to format it using -
INSERT INTO table
VALUES ('&p_cname', '&p_cyear' || ' ' || '&p_color' || ' ' || '&p_make' || ' ' || '&p_model' ||
|| ' ' || '&p_trim' || ' ' || '&p_enginetype' || ' ' || '&p_option' || '(' || '&p_ocode' || ')');
BUT IT DOED NOT WORK.

The error you pasted into comments doesn't correspond to the code in your question. If I execute the code I get:
SQL> #test
Enter Customer Name: a
Enter Car Year: b
Enter Car Color: c
Enter Car Make: d
Enter Car Model: e
Enter Car Trim: f
Enter Car Engine Type: g
Enter Option Name: h
Enter Option Code: i
old 2: VALUES ('&p_cname', '&p_cyear' || ' ' || '&p_color' || ' ' || '&p_make' || ' ' || '&p_model' ||
new 2: VALUES ('a', 'b' || ' ' || 'c' || ' ' || 'd' || ' ' || 'e' ||
old 3: || ' ' || '&p_trim' || ' ' || '&p_enginetype' || ' ' || '&p_option' || '(' || '&p_ocode' || ')')
new 3: || ' ' || 'f' || ' ' || 'g' || ' ' || 'h' || '(' || 'i' || ')')
|| ' ' || 'f' || ' ' || 'g' || ' ' || 'h' || '(' || 'i' || ')')
*
ERROR at line 3:
ORA-00936: missing expression
SQL>
That's because you have two concatenation operators missing it's second operand:
'&p_model' || || ' ' || '&p_trim'
Eliminate the extra operator and the insert works:
'&p_model' || ' ' || '&p_trim'

Related

Optimising changing column types

I've got an ETL script which changes the column types of a table to desired type and updates the data. The script works perfectly but I was wondering if there was a better & quicker way of doing it? Working in Redshift.
Current procedure;
CREATE or REPLACE PROCEDURE p_alter_staging_tbls() AS $$
DECLARE
row RECORD;
BEGIN
FOR row IN select * from
(
select distinct table_name, column_name,data_type from staging.staging_col_info_v a order by a.table_name asc
)
loop
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ADD COLUMN ' || concat('new_',row.column_name) || ' ' || row.data_type ;
EXECUTE 'UPDATE staging.' || row.table_name || ' ' || 'SET ' || concat('new_',row.column_name) || ' ' || '=' || ' ' || row.column_name || '::' || row.data_type ;
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'DROP COLUMN ' || row.column_name ;
execute 'ALTER TABLE staging.' || row.table_name || ' ' || 'RENAME COLUMN '|| concat('new_',row.column_name) || ' ' || 'TO ' || row.column_name;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
For optimization, you can check if the data type needs to be changed or if you already have the correct type and size.
For this purpose you can use a query like this:
SELECT table_schema, table_name, column_name, data_type,
column_default, character_maximum_length, numeric_precision
FROM information_schema.columns
WHERE table_schema = 'staging'
AND table_name = row.table_name
AND column_name = row.column_name
and then check if "data_type" AND "numeric_precision" is different, in this case you can alter the column.
You can also consider to not create a new column, but you can use:
ALTER TABLE table_name
ALTER COLUMN column_name [SET DATA] TYPE new_data_type;
instead of:
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ADD COLUMN ' || concat('new_',row.column_name) || ' ' || row.data_type ;
EXECUTE 'UPDATE staging.' || row.table_name || ' ' || 'SET ' || concat('new_',row.column_name) || ' ' || '=' || ' ' || row.column_name || '::' || row.data_type ;
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'DROP COLUMN ' || row.column_name ;
execute 'ALTER TABLE staging.' || row.table_name || ' ' || 'RENAME COLUMN '|| concat('new_',row.column_name) || ' ' || 'TO ' || row.column_name;
you can use this:
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ALTER COLUMN '|| row.column_name || ' ' || 'TYPE ' || || row.data_type;

Adding spaces to a piped concatenation

How do I change my select statement so that the following will return spaces between the concatenated columns?
The current query is similar to:
SELECT
address_line1 || address_line2 || address_line3 || address_line4 || city || state || county || province || country || zip as address
FROM
table
Many thanks
Just add space characters in between the fields:
SELECT
address_line1 || ' ' || address_line2 || ' ' || address_line3 || ' ' ||
address_line4 || ' ' || city || ' ' || state || ' ' || county || ' ' ||
province || ' ' || country || ' ' || zip AS address
FROM yourTable;

String Replace a joined SQL SELECT statement

I'm wondering if it is possibly to complete a string replace on a joined SQL statement. For example, my query is:
SELECT (SITE_NAME || ', ' || LOT_NUMBER || ' ' || UNIT_TYPE || ' ' || LEVEL_NUMBER
|| ' ' || UNIT_NUMBER || ' ' || ROAD_NUMBER_1 || ' ' || ROAD_NUMBER_2 || ' ' || ROAD_NAME
|| ' ' || ROAD_TYPE || ' ' || ROAD_SUFFIX || ', ' || SUBURB || ', ' || STATE) AS address
FROM ADDRESS_LOOKUP_TOOL
WHERE ADD_ID = :P1_ADD_ID;
This statement works perfectly.... providing every single address field is populated. If only some sections are populated (i.e. there is no site name, or road suffix), there are additional commas or spaces.
Here is an example of a good select:
House of Dom, Lot 1 Suite 4 4D 119 Fake St South, Domtopia, QLD
Here is an example of a flawed select:
, Lot 1 Suite 4 4D 119 Fake St , Domtopia, QLD
Is it possibly to do a string replace on the alias where I could say, for example replace(address, ' ,', ',') (Where "space comma" just becomes "comma"), or is there a better way I should be structuring my select to pick this up in one go?
An additional note: This is all being completed with in Oracle's Application Express (ApEx) if this makes a difference.
I am very new to SQL, so I apologise in advance if I ask any basic follow up questions!
Thank you!
Dominic
You don't need to do it on the alias. Just do it on the expression itself.
SELECT REPLACE(
(SITE_NAME || ', ' || LOT_NUMBER || ' ' || UNIT_TYPE || ' ' || LEVEL_NUMBER
|| ' ' || UNIT_NUMBER || ' ' || ROAD_NUMBER_1 || ' ' || ROAD_NUMBER_2 || ' ' || ROAD_NAME
|| ' ' || ROAD_TYPE || ' ' || ROAD_SUFFIX || ', ' || SUBURB || ', ' || STATE),
' ,', ',') AS address
FROM ADDRESS_LOOKUP_TOOL
WHERE ADD_ID = :P1_ADD_ID;

How to Select 2 Different Names from same table and display them on the Condition

I have this Query
SELECT NAME_NO
,(
SELECT FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE
FROM NAMES
WHERE NAME_NO = 1
) AS "NAME1: NAME, DOB, PHONE"
,(
SELECT FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE
FROM NAMES
WHERE NAME_NO = 2
) AS "NAME2: NAME, DOB, PHONE"
,
FROM NAMES;
I get this error:
01427. 00000 - "single-row subquery returns more than one row"
I need multiple records.
What is the best method to solve this?
Try this one:
SELECT NAME_NO, FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE AS "NAME1: NAME, DOB, PHONE"
FROM NAMES
UNION
SELECT FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE AS "NAME2: NAME, DOB, PHONE"
FROM NAMES
WHERE NAME_NO = 2
or this one:
WITH N1 AS (
SELECT NAME_NO,FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE AS "VAL"
FROM NAMES
WHERE NAME_NO = 1),
N2 AS (
SELECT FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE AS "VAL"
FROM NAMES
WHERE NAME_NO = 2)
SELECT
NAME_NO,VAL
FROM N1,N2;
You need to use PIVOT. Try this
Select A "NAME1: NAME, DOB, PHONE" , B "NAME2: NAME, DOB, PHONE" from (SELECT FNAME || ' ' || LNAME || ' ' || BIRTH_DT || ' ' || ' ' || PHONE N, NAME_NO
FROM NAMES)
Pivot
(Max(N) for NAME_NO in (1 as A, 2 as B)
);

How would I return a salary + a 5% raise?

I am trying to return a salary + a 5% raise. I thought the following code would work but it gives me an error. Can anyone help?
SELECT last_name || ' ' || salary || ' ' ||salary*.05+salary || ' ' FROM f_staffs;
The trick is this:
SELECT last_name || ' ' || salary || ' ' || (1.05*salary) || ' ' FROM f_staffs;
are you need all in one field? if yes assuming oracle:
SELECT last_name || ' ' || to_char(salary) || ' ' ||to_char(salary*.05+salary) || ' ' FROM f_staffs;