Comparing varchar2 in Oracle with different charsets? - sql

I have a column in a table that is defined as Varchar2(4000) called tbl_varchar.
I get a input argument from the client to a stored procedure that is varchar2(4000) as well. I call that input_varchar.
I want to update only if the contents has changed:
Update table t SET tbl_varchar = input_varchar, updated = sysdate
WHERE key = input_key and tbl_varchar != input_varchar;
I am running this with the same input several times and see that my timestamp is updated everytime but the varchar data doesn't seem to be change.
Can this have anything to do with different char sets on the client and database? If so, what is the best way to confirm it? I don't have any control of the client.

If that's about charset you can try:
Update table t SET tbl_varchar = input_varchar, updated = sysdate
WHERE key = input_key and convert(tbl_varchar, 'US7ASCII') != convert(input_varchar, 'US7ASCII');
Or put your charset instead of 'US7ASCII'
I'd also add trim() both values. Maybe issue is with some whitespaces.

Related

Trigger to convert empty string to 'null' before it posts in SQL Server decimal column

I've got a front table that essentially matches our SSMS database table t_myTable. Some columns I'm having problems with are those with numeric data types in the db. They are set to allow null, but from the front end when the user deletes the numeric value and tries to send a blank value, it's not posting to the database. I suspect because this value is sent back as an empty string "" which does not translate to the null allowable data type.
Is there a trigger I can create to convert these empty strings into null on insert and update to the database? Or, perhaps a trigger would already happen too late in the process and I need to handle this on the front end or API portion instead?
We'll call my table t_myTable and the column myNumericColumn.
I could also be wrong and perhaps this 'empty string' issue is not the source of my problem. But I suspect that it is.
As #DaleBurrell noted, the proper place to handle data validation is in the application layer. You can wrap each of the potentially problematic values in a NULLIF function, which will convert the value to a NULL if an empty string is passed to it.
The syntax would be along these lines:
SELECT
...
,NULLIF(ColumnName, '') AS ColumnName
select nullif(Column1, '') from tablename
SQL Server doesn't allow to convert an empty string to the numeric data type. Hence the trigger is useless in this case, even INSTEAD OF one: SQL Server will check the conversion before inserting.
SELECT CAST('' AS numeric(18,2)) -- Error converting data type varchar to numeric
CREATE TABLE tab1 (col1 numeric(18,2) NULL);
INSERT INTO tab1 (col1) VALUES(''); -- Error converting data type varchar to numeric
As you didn't mention this error, the client should pass something other than ''. The problem can be found with SQL Profiler: you need to run it and see what exact SQL statement is executing to insert data into the table.

Update PostgreSQL hstore field with sql variable

I have table files which has hstore column details. In my sql statement I insert data to it:
UPDATE files SET details = 'new_users=>new_users_count'::hstore where id = v_file_id;
but I want to update this hstore field not with string but with variable that is available in my sql statement. How can I do this?
PL/pgSQL can't detect variables inside a string literal. You need to use the "constructor" method of the hstore type to pass a variable:
UPDATE files
SET details = hstore('new_users', p_new_user_count)
where id = v_file_id;
If p_new_user_count is defined as a number (rather than a varchar or text) you need to cast this to a text value:
UPDATE files
SET details = hstore('new_users', p_new_user_count::text)
where id = v_file_id;
Edit after the question was changed:
To do this for multiple variables you can either concatenate two hstore values:
details = hstore('new_users', p_new_user_count::text)||hstore('post_count', p_post_count::text)
or use arrays:
details = hstore(array['new_users','post_count'], array[p_user_count, p_post_count]::text[]);
This is all documented in the manual: http://www.postgresql.org/docs/current/static/hstore.html
In case if you need to replace only new_users in the hstore then
UPDATE files
SET details = details || hstore('new_users', p_new_user_count::text)
where id = v_file_id;
It will replace new_users if already present in the column or add a new entry.

How to update a boolean field in Oracle table

I am a novice Oracle user. I wanted to update a boolean field in my table for one of the record. Which one of these statements is correct ?
update MyTable set myBooleanColumn = 1 where UserId= 'xx12345';
or
update MyTable set myBooleanColumn = '1' where UserId= 'xx12345';
any help is greatly appreciated!! thanks !
It depends on how the field is defined.
If its defined as a CHAR(1) field, then you can store 'Y'/'N' or 'T'/'F' in it. To update the field, you'd use the quotes as it would be a string literal.
UPDATE TestTable set myCharBooleanColumn = 'Y';
If the field is defined as NUMERIC, then the convention is 0=false and 1 or -1 is true (I've seen both).
UPDATE TestTable set myNumericBooleanColumn = 1;
Many people will advocate the CHAR(1) approach, but in the real world - you see both. It depends on how the boolean is implemented.
You can read more in Oracle's docs on Datatypes
http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm
There is no such thing as a Boolean field in Oracle so your field is either a numeric field or a character field. If it's a numeric field you don't need to quote the number; if it's a character field you should quote the string.
You can find out the type of the column by querying USER_TAB_COLUMNS:
select *
from user_tab_columns
where table_name = 'MYTABLE'
and column_name = 'MYBOOLEANCOLUMN'
or by describing the table.
There is nothing as Boolean field in Oracle.
The best what you can do is to create the table like this:-
create table ABC(bool char(1) check (bool in ('N','Y'));
Then simple update like
UPDATE ABC set bool = 'Y';
WHY TAKING CHAR?
There is no support for BOOLEAN, BIT, or TINYINT data types so char would be the best as it takes 1 byte

comparing input parameter with xml value using like in sql

I have an SQL table with a column which stores xml like this
<AdditionalInfo><RegistrantID>16279</RegistrantID></AdditionalInfo>
I have created a stored procedure like this:
CREATE PROC hr_GetJobStatusByRegistrantId
#registrantId VARCHAR
AS
BEGIN
SELECT TOP 1
[IsSubscribed]
FROM [Hrge].[dbo].[hr_Jobs]
where AdditionalInfo LIKE '%<AdditionalInfo><RegistrantID>%' + #registrantId + '%</RegistrantID></AdditionalInfo>%'
END
When I run this stored procedure, I get null:
exec hr_GetJobStatusByRegistrantId '16279'
If I make this parameter integer then I get convertion to int error.
Please suggest me solution to this.
(Just expanding the comment into an answer)
You should always specify the width of a char or a varchar field, because unless you do the default kicks in. The documentation says:
When n is not specified in a data definition or variable declaration
statement, the default length is 1. When n is not specified when using
the CAST and CONVERT functions, the default length is 30.
which means that in your case you have actually defined #registrantId as VARCHAR(1) so the value of '16279' was trimmed to a single character ('1') and you actually searched for
%<AdditionalInfo><RegistrantID>%1%</RegistrantID></AdditionalInfo>%
in the database. This actually returned the IsSubscribed flag for the first record it found in the DB that had a '1' anywhere in the RegistrantID field. You got lucky that the value was something wrong, so you noticed it.
Additionally you are using % around your parameter. This means that when you search for a RegistrantID of 123, you'll get results for 123, 1234, 2123, 51236, etc, etc, and then just take the first one, whichever that one is (decided by the database, since there is no order clause). It's my guess that you need an exact match, so you should remove those, and just use
'%<AdditionalInfo><RegistrantID>' + #registrantId
+ '</RegistrantID></AdditionalInfo>%'
Also, it the RegistrantId is actually a number, it would be nice if the interface of the procedure reflected that, so it could be defined with
#registrantId int
and then converted to a string in the query
'%<AdditionalInfo><RegistrantID>' + cast(#registrantId as varchar(10))
+ '</RegistrantID></AdditionalInfo>%'

Load Data Infile - negative decimal truncated (to positive number)

I am having trouble loading decimal data into a database - specifically, my negative numbers are getting truncated, and I can't figure it out.
Here is what my query looks like:
> CREATE TABLE IF NOT EXISTS mytable (id INT(12) NOT NULL AUTO_INCREMENT,
mydecimal DECIMAL(13,2),PRIMARY KEY(id));
> LOAD DATA INFILE 'data.dat' INTO TABLE mytable FIELDS TERMINATED BY ';';
And the data.dat that I'm loading:
;000000019.50 ;
;000000029.50-;
;000000049.50 ;
When it completes, giving me a warning that "Data truncated for column 'mydecimal' at row 2." And when I look at the data, it's stored as positive number. Any ideas how to fix this?
The best way to handle data abnormalities like this in the input file is to load them into a local variable, then set the actual column value based on a transformation of the local variable.
In your case, you can load the strings into a local variable, then either leave it alone or multiply by negative one depending on whether it ends with a minus sign.
Something like this should work for you:
LOAD DATA INFILE 'data.dat'
INTO TABLE mytable FIELDS TERMINATED BY ';'
(id,#mydecimal)
set mydecimal = IF(#mydecimal like '%-',#mydecimal * -1,#mydecimal);
I'm not sure why you're putting the minus sign after the number rather than before it. Does it work when you place the '-' sign at the start of the line?
you can consider this
CREATE TABLE IF NOT EXISTS mytable (id INT(12) NOT NULL AUTO_INCREMENT,
mydecimal varchar(255),PRIMARY KEY(id));
LOAD DATA INFILE 'data.dat' INTO TABLE mytable FIELDS TERMINATED BY ';';
update mytable set mydecimal =
cast(mydecimal as decimal(13,2))*if (substring(mydecimal, -1)='-', -1, 1);
alter table mytable modify column mydecimal decimal(13,2) signed;