How to insert a blank value instead of NULL in Columns other than String datatype in hive - hadoop

I have a create statement like
CREATE TABLE temp_tbl (EmpId String,Salary int);
I would like to insert an employee id and a blank value into table.
So What I have done is
insert overwrite table temp_tbl select '013' as EmpId,'' as Salary from tbl;
hive> select * from temp_tbl;
OK
013 NULL
But expected result is
hive> select * from temp_tbl;
OK
013 NULL ---> Blank instead of NULL
Also tried with "". Still I get it as NULL instead of blank
3.Tried to create table with serialization property
CREATE TABLE temp_tbl (EmpId String,Salary int) TBLPROPERTIES ('serialization.null.format' = '');
That too didn't change NULL value to blank.
What can be the workaround for the same.

Use Case while selecting the data.
Select
(CASE
WHEN columnName is null THEN ''
ELSE columnName
END) as 'Result' from temp_tbl;

All types except strings/varchar/char and some complex types like array, in Hive cannot be blank, only NULL is possible. Empty string '' is quite normal value of type String. You can produce empty array() as well (Array with zero size).
As a workaround, you can use some predefined values which are not normally in your data to represent some special numeric values, like -99999. Alternatively you can store your numeric values in a String column, in such case you will be able to have empty values in it. But it's not possible to assign (cast) empty strings to numeric types, because such empty value is not allowed.
If you try to assign empty string to numeric column or cast to numeric type, the result will be the same as if you are converting non-numeric string to numeric - NULL (in Hive if not possible to cast, it returns NULL) or get java.lang.NumberFormatException in Java.

Knowing that datatype Int can be either NULL or integer , I'd think of how to work around the problem.
I have the impression that 0 can do the job. Why can it not?
If 1 is not ideal, why not create a new temp_employees_with_no_salary table?
If 2 is not ideal, can you afford to change the datatype of temp_tbl.Salary from Int to String, then use CAST(Salary AS INT) to work with it?

Related

ORACLE SQL Replace null values with previous value depending on other fields

From a query I want to replace the null values of the "cod_account" field, the condition to fill this field is that it must take the previous value only if it satisfies that the previous records of other fields (cod_agen, cod_sub, no_prod) are equal.
Currently it is like this:
enter image description here
what is desired is
enter image description here
thanks for your advice. i solve it
use with to separate queries.
select
case when cod_account is null and class ='Primary'
then null
when cod_account is null and class='Secundary'
then (select cod_account from principals P--principals is table create in a "with"
where fa.cod_agen=P.cod_agen
and fa.cod_sub=P.cod_sub
and fa.no_prod=P.no_prod
and p.class='secundary'
)
...
from signs fa

Row is missing while exploding a clob data in oracle

I am trying to explode below data which contains a clob type, but while clob type is containing null, the complete row is missing out.
SEC is having a CLOB data type containg array data. While SEC is having null, below query is not giving any output .
select
CRE_DATE,
serv,
rg,
id,
hos_id,
state
from table1 a,
JSON_TABLE(a.SEC,'$[*]' COLUMNS (h_id varchar2(256) path '$' null on empty ));
Just use outer apply:
select
CRE_DATE,
serv,
rg,
id,
hos_id,
state
from table1 a
outer apply JSON_TABLE(a.SEC,'$[*]' COLUMNS (h_id varchar2(256) path '$' null on empty ));

Oracle user defined records

In Oracle PL/SQL records we can use anchor datatypes (including %TYPE and %ROWTYPE) to define the fields.
When I populate a record from a query, in my select clause I want type conversion. Is that possible using an Oracle built-in function or some other approach?
In this example scenario I am using a simple decode function to perform a conversion:
DECLARE
TYPE TEST_RECORD IS RECORD(
FIRST_NAME EMPLOYEE_MT.FIRST_NAME%TYPE,
LAST_NAME EMPLOYEE_MT.LAST_NAME%TYPE,
MARITIAL_STATUS EMPLOYEE_MT.MARITAL_STATUS%TYPE);
EMPLOYEE_NAME TEST_RECORD;
BEGIN
SELECT EMP.FIRST_NAME,
EMP.LAST_NAME,
DECODE(EMP.MARITAL_STATUS, 1, 'MARRIED', 0, 'UN-MARRIED')
INTO EMPLOYEE_NAME
FROM EMPLOYEE_MT EMP
WHERE EMP.EMPLOYEE_ID = 1;
DBMS_OUTPUT.put_line(EMPLOYEE_NAME.MARITIAL_STATUS);
END;
which gets error:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 9
You have defined your record type with the maritial_status (shouldn't that be marital_status?) field using the same data type as the table column. From your decode that appears to be a number data type. You're then trying to set the record's field value to a string, either 'MARRIED' or 'UN-MARRIED', when that field is expecting a number. Clearly neither of those strings can be converted to a number, hence the error you're getting.
If you want the record to store the string value, you'll have to define it like that - explicitly as a string, rather than using %TYPE:
DECLARE
TYPE TEST_RECORD IS RECORD(
FIRST_NAME EMPLOYEE_MT.FIRST_NAME%TYPE,
LAST_NAME EMPLOYEE_MT.LAST_NAME%TYPE,
MARITAL_STATUS VARCHAR2(10));
...
DBMS_OUTPUT.put_line(EMPLOYEE_NAME.MARITAL_STATUS);
...
You can't do that automatically using %TYPE as the data type just doesn't match. You've explicitly told Oracle that you want the field's data type to be a number, so Oracle isn't going to let you put a string in that field instead. It isn't about there not being a built-in function, it just doesn't make sense.
This also means you can't use %ROWTYPE if you're changing the data type either (unless your modified value can be implicitly converted back to the column data type).

Cannot update a row with a bind variable in UPDATE statement

I am using Oracle SQL Developer 4.0.0.13.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = :abc;
Field Definition : emp_device char(20 byte)
Value is : 99998000000008880999 (This value is present in the table)
When I run the above query in SQL developer it asks me to give the value for the bind variable, which I paste in the text box and it returns 0 rows updated.
But when I remove the bind variable in the update query and specify the actual value, it updates the column value. Below is the query.
Query:
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = 99998000000008880999 ;
---(works)
Also, when I add some trailing spaces in the bind variable text box and trim the emp_device column, it updates the column. Below is the query.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = trim(:abc);
-- (works --- :abc value is '99998000000008880999 ')
I do not know what is wrong with it. Can someone please take a look and suggest a solution.
You are using CHAR type for your emp_device datatype. Note that CHAR type always blank pads the resulting string out to a fixed width.read this.
You should use VARCHAR2 as datatype if you are expecting a string or just NUMBER as your example consists purely of numeric values.
in dialog box enter your parameter as '99998000000008880999' use apostrophe chars.

"Create table as select" does not preserve not null

I am trying to use the "Create Table As Select" feature from Oracle to do a fast update. The problem I am seeing is that the "Null" field is not being preserved.
I defined the following table:
create table mytable(
accountname varchar2(40) not null,
username varchar2(40)
);
When I do a raw CTAS, the NOT NULL on account is preserved:
create table ctamytable as select * from mytable;
describe ctamytable;
Name Null Type
----------- -------- ------------
ACCOUNTNAME NOT NULL VARCHAR2(40)
USERNAME VARCHAR2(40)
However, when I do a replace on accountname, the NOT NULL is not preserved.
create table ctamytable as
select replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
describe ctamytable;
Name Null Type
----------- ---- -------------
ACCOUNTNAME VARCHAR2(160)
USERNAME VARCHAR2(40)
Notice that the accountname field no longer has a null, and the varchar2 field went from 40 to 160 characters. Has anyone seen this before?
This is because you are no longer selecting ACCOUNTNAME, which has a column definition and meta-data. Rather you are selecting a STRING, the result of the replace function, which doesn't have any meta-data. This is a different data type entirely.
A (potentially) better way that might work is to create the table using a query with the original columns, but with a WHERE clause that guarantees 0 rows.
Then you can insert in to the table normally with your actual SELECT.
By having query of 0 rows, you'll still get the column meta-data, so the table should be created, but no rows will be inserted. Make sure you make your WHERE clause something fast, like WHERE primary_key = -999999, some number you know would never exist.
Another option here is to define the columns when you call the CREATE TABLE AS SELECT. It is possible to list the column names and include constraints while excluding the data types.
An example is shown below:
create table ctamytable (
accountname not null,
username
)
as
select
replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
Be aware that although this syntax is valid, you cannot include the data type. Also, explicitly declaring all the columns somewhat defeats the purpose of using CREATE TABLE AS SELECT.

Resources