Showing posts with label odd. Show all posts
Showing posts with label odd. Show all posts

Wednesday, March 28, 2012

HELP! Strange behavior using t-sql REPLACE function

I am seeing very odd behavior with the t-sql REPLACE funtion.

I am trying to wipe out the 'T' character (unicode value 222) with a space character (' ' unicode value 32) and it appears to be replacing occurrences of 'th' together as well. Here are some selects to show this behavior:

select nchar(unicode('T'))
select nchar(unicode(' '))
select unicode('T')
select unicode(' ')
select replace('Urban & Ethnic', nchar(unicode('T')), nchar(unicode(' ')))
select replace('Urban T Ethnic', nchar(unicode('T')), nchar(unicode(' ')))
select replace('Urban & Ethnic', nchar(222), nchar(32))
select replace('Urban T Ethnic', nchar(222), nchar(32))
select replace('Urban & Ethnic', 'T', ' ')
select replace('Urban T Ethnic', 'T', ' ')

NOTICE that the last two statements:

select replace('Urban & Ethnic', 'T', ' ') - RESULT 'Urban & Ethnic'
select replace('Urban T Ethnic', 'T', ' ') - RESULT 'Urban Ethnic'

...work properly, while the other ones dont:

select replace('Urban & Ethnic', nchar(unicode('T')), nchar(unicode(' '))) - RESULT 'Urban & E nic'
select replace('Urban T Ethnic', nchar(unicode('T')), nchar(unicode(' '))) - RESULT 'Urban E nic'
select replace('Urban & Ethnic', nchar(222), nchar(32)) - RESULT 'Urban & E nic'
select replace('Urban T Ethnic', nchar(222), nchar(32)) - RESULT 'Urban E nic'

This function ONLY seems to work with the character representation, any attempt to convert an integer value to a character representation fails miserably...

Please advise, and thanks for your help in advance.

It seems that the collation the active database uses treats "th" and "T" as the same character. To fix this, change the database collation to something more appropriate, or use tricks like the following in your queries:

select replace(N'Urban T Ethnic' COLLATE Latin1_General_BIN, N'T', N' ')

By forcing the collation to BIN (binary), a binary comparison is done, which doesn't do fancy character-equivilancy stuff.

-Ryan

|||

Thanks!

sp_helpsort reveals the default collation = Latin1-General, blah, blah, blah, etc...

I even tried to convert EVERYTHING to binary var types within the query and it STILL came up with the wrong result.

Thanks again for your help. I didn't even consider changing the COLLATION type in the query itself...

sql

Monday, March 12, 2012

HELP! Data Conversion Rounding Problem

I have a somehwat odd situation. I have a field on table A defined as
float. It is being written to a varchar(15) field on table B. If the
field on A is NULL I want the field on B to be '0'. It cannot have
two decimal places. It must be a single character of zero.
If the field in table A is a number, it must be written to table B as
the same number. Here are some examples:
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.21 <-- This is what I want
35444.79 35444.79 <-- This is what I want
My problem is with the last two. Any amount > 9,999.99 rounds the
second decimal value. So in the example above I get this (which is
wrong):
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.2 <-- This is wrong
35444.79 35444.8 <-- This is wrong
I've tried multiple way of using CONVERT and CAST. When I use decimal
or money I get the two decimal places for all values correct. However,
now my '0' turns into '0.00' (which is wrong). I need it to not have
the two decimal places.
Any suggestions?Separate presentation from data. SQL Server returns data values and the value 0 is the same as the
value 0.00. The client application presents the binary values returned by SQL Server in a
human-readable form (like number with decimal points). If you didn't write the client app yourself,
i.e., if you use something like QA, SSMS, OSQL, ISQL, SQLCMD, Reporting Services, etc, then these
tools will present the values according to the datatype *for the column'. I.e., a tool might assume
that the money datatype will be presented with two decimals. Or 4. IT is the person writing the too
who makes these decision, but it applies to all values for the column. The only way to not being at
the mercy of the tool vendor is to convert to strings, but that will lead to some potentially
lengthy CASE expressions in the SELECT statement. So, my suggestion is to handle this in the client
app. All client app designed for end users has functionality for formatting data (like for instance
a format() function).
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1174935075.294994.16170@.l75g2000hse.googlegroups.com...
>I have a somehwat odd situation. I have a field on table A defined as
> float. It is being written to a varchar(15) field on table B. If the
> field on A is NULL I want the field on B to be '0'. It cannot have
> two decimal places. It must be a single character of zero.
> If the field in table A is a number, it must be written to table B as
> the same number. Here are some examples:
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.21 <-- This is what I want
> 35444.79 35444.79 <-- This is what I want
> My problem is with the last two. Any amount > 9,999.99 rounds the
> second decimal value. So in the example above I get this (which is
> wrong):
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.2 <-- This is wrong
> 35444.79 35444.8 <-- This is wrong
> I've tried multiple way of using CONVERT and CAST. When I use decimal
> or money I get the two decimal places for all values correct. However,
> now my '0' turns into '0.00' (which is wrong). I need it to not have
> the two decimal places.
> Any suggestions?
>|||Thanks Tibor.
Unfortunately, handling this at the UI end is not an option. I'm
converting an app (from Access). I need the data to be exactly the
same. I unable to change the UI at this time.|||Plus, I would like to know why SQL Server is rounding that value. To
me this looks like a defect. It should not be rounding the value.|||I'm not sure I understand your comments about rounding. Let's work with executable code instead.
Can, you, based on below, describe when you want:
CREATE TABLE y(c1 float)
INSERT INTO y (c1) VALUES (NULL)
INSERT INTO y (c1) VALUES (123.45)
INSERT INTO y (c1) VALUES (555.70)
INSERT INTO y (c1) VALUES (35444.21)
INSERT INTO y (c1) VALUES (35444.79)
SELECT
CASE WHEN c1 IS NULL THEN 0 ELSE c1 END
FROM y
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1174942335.112146.304030@.n59g2000hsh.googlegroups.com...
> Plus, I would like to know why SQL Server is rounding that value. To
> me this looks like a defect. It should not be rounding the value.
>|||The problem is in the last two writes in the example I gave.
Hopefully this explains it more...Run this code to create table Z.
Run this:
---
CREATE TABLE z(c1 varchar(15))
INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE y.c1
END FROM y
Here is what ends up in z for me:
---
0
123.45
555.7
35444.2
35444.8
The last two records get rounded to one decimal place. Why does that
happen? When I cast it as money, the values do not round:
INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE
CAST(y.c1 AS Money) END FROM y
0.00
123.45
555.70
35444.21
35444.79
But now the '0' is '0.00'. Which is NOT what I want.|||I really don't know why SQL Server would cast the float values that way. In general, I avoid float
being what sometime is called an approximate datatype. So, it seems that when SQL Server converts
from float to varchar, you see some funny things. I would suggest you cast to something else, like
decimal And if you *really* want to do presentation logic in the engine, you can convert NULL to 0,
cast to varchar, then replace '0.00' with 0. See below:
INSERT INTO z ([c1])
SELECT CASE WHEN c = '0.00' THEN '0' ELSE c END
FROM
(
SELECT
CAST(
CAST(
ISNULL(y.c1, 0)
AS decimal (9,2))
AS varchar(15)) AS c
FROM y
) AS inr
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1175032433.780317.287070@.d57g2000hsg.googlegroups.com...
> The problem is in the last two writes in the example I gave.
> Hopefully this explains it more...Run this code to create table Z.
> Run this:
> ---
> CREATE TABLE z(c1 varchar(15))
> INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE y.c1
> END FROM y
> Here is what ends up in z for me:
> ---
> 0
> 123.45
> 555.7
> 35444.2
> 35444.8
> The last two records get rounded to one decimal place. Why does that
> happen? When I cast it as money, the values do not round:
> INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE
> CAST(y.c1 AS Money) END FROM y
> 0.00
> 123.45
> 555.70
> 35444.21
> 35444.79
> But now the '0' is '0.00'. Which is NOT what I want.
>|||Thanks Tibor! That was helpful.

HELP! Data Conversion Rounding Problem

I have a somehwat odd situation. I have a field on table A defined as
float. It is being written to a varchar(15) field on table B. If the
field on A is NULL I want the field on B to be '0'. It cannot have
two decimal places. It must be a single character of zero.
If the field in table A is a number, it must be written to table B as
the same number. Here are some examples:
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.21 <-- This is what I want
35444.79 35444.79 <-- This is what I want
My problem is with the last two. Any amount > 9,999.99 rounds the
second decimal value. So in the example above I get this (which is
wrong):
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.2 <-- This is wrong
35444.79 35444.8 <-- This is wrong
I've tried multiple way of using CONVERT and CAST. When I use decimal
or money I get the two decimal places for all values correct. However,
now my '0' turns into '0.00' (which is wrong). I need it to not have
the two decimal places.
Any suggestions?Separate presentation from data. SQL Server returns data values and the valu
e 0 is the same as the
value 0.00. The client application presents the binary values returned by SQ
L Server in a
human-readable form (like number with decimal points). If you didn't write t
he client app yourself,
i.e., if you use something like QA, SSMS, OSQL, ISQL, SQLCMD, Reporting Serv
ices, etc, then these
tools will present the values according to the datatype *for the column'. I.
e., a tool might assume
that the money datatype will be presented with two decimals. Or 4. IT is the
person writing the too
who makes these decision, but it applies to all values for the column. The o
nly way to not being at
the mercy of the tool vendor is to convert to strings, but that will lead to
some potentially
lengthy CASE expressions in the SELECT statement. So, my suggestion is to ha
ndle this in the client
app. All client app designed for end users has functionality for formatting
data (like for instance
a format() function).
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1174935075.294994.16170@.l75g2000hse.googlegroups.com...
>I have a somehwat odd situation. I have a field on table A defined as
> float. It is being written to a varchar(15) field on table B. If the
> field on A is NULL I want the field on B to be '0'. It cannot have
> two decimal places. It must be a single character of zero.
> If the field in table A is a number, it must be written to table B as
> the same number. Here are some examples:
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.21 <-- This is what I want
> 35444.79 35444.79 <-- This is what I want
> My problem is with the last two. Any amount > 9,999.99 rounds the
> second decimal value. So in the example above I get this (which is
> wrong):
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.2 <-- This is wrong
> 35444.79 35444.8 <-- This is wrong
> I've tried multiple way of using CONVERT and CAST. When I use decimal
> or money I get the two decimal places for all values correct. However,
> now my '0' turns into '0.00' (which is wrong). I need it to not have
> the two decimal places.
> Any suggestions?
>

HELP! Data Conversion Rounding Problem

I have a somehwat odd situation. I have a field on table A defined as
float. It is being written to a varchar(15) field on table B. If the
field on A is NULL I want the field on B to be '0'. It cannot have
two decimal places. It must be a single character of zero.
If the field in table A is a number, it must be written to table B as
the same number. Here are some examples:
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.21 <-- This is what I want
35444.79 35444.79 <-- This is what I want
My problem is with the last two. Any amount > 9,999.99 rounds the
second decimal value. So in the example above I get this (which is
wrong):
A B
NULL 0
123.45 123.45
555.70 555.7
35444.21 35444.2 <-- This is wrong
35444.79 35444.8 <-- This is wrong
I've tried multiple way of using CONVERT and CAST. When I use decimal
or money I get the two decimal places for all values correct. However,
now my '0' turns into '0.00' (which is wrong). I need it to not have
the two decimal places.
Any suggestions?
Separate presentation from data. SQL Server returns data values and the value 0 is the same as the
value 0.00. The client application presents the binary values returned by SQL Server in a
human-readable form (like number with decimal points). If you didn't write the client app yourself,
i.e., if you use something like QA, SSMS, OSQL, ISQL, SQLCMD, Reporting Services, etc, then these
tools will present the values according to the datatype *for the column'. I.e., a tool might assume
that the money datatype will be presented with two decimals. Or 4. IT is the person writing the too
who makes these decision, but it applies to all values for the column. The only way to not being at
the mercy of the tool vendor is to convert to strings, but that will lead to some potentially
lengthy CASE expressions in the SELECT statement. So, my suggestion is to handle this in the client
app. All client app designed for end users has functionality for formatting data (like for instance
a format() function).
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1174935075.294994.16170@.l75g2000hse.googlegro ups.com...
>I have a somehwat odd situation. I have a field on table A defined as
> float. It is being written to a varchar(15) field on table B. If the
> field on A is NULL I want the field on B to be '0'. It cannot have
> two decimal places. It must be a single character of zero.
> If the field in table A is a number, it must be written to table B as
> the same number. Here are some examples:
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.21 <-- This is what I want
> 35444.79 35444.79 <-- This is what I want
> My problem is with the last two. Any amount > 9,999.99 rounds the
> second decimal value. So in the example above I get this (which is
> wrong):
> A B
> NULL 0
> 123.45 123.45
> 555.70 555.7
> 35444.21 35444.2 <-- This is wrong
> 35444.79 35444.8 <-- This is wrong
> I've tried multiple way of using CONVERT and CAST. When I use decimal
> or money I get the two decimal places for all values correct. However,
> now my '0' turns into '0.00' (which is wrong). I need it to not have
> the two decimal places.
> Any suggestions?
>
|||Thanks Tibor.
Unfortunately, handling this at the UI end is not an option. I'm
converting an app (from Access). I need the data to be exactly the
same. I unable to change the UI at this time.
|||Plus, I would like to know why SQL Server is rounding that value. To
me this looks like a defect. It should not be rounding the value.
|||I'm not sure I understand your comments about rounding. Let's work with executable code instead.
Can, you, based on below, describe when you want:
CREATE TABLE y(c1 float)
INSERT INTO y (c1) VALUES (NULL)
INSERT INTO y (c1) VALUES (123.45)
INSERT INTO y (c1) VALUES (555.70)
INSERT INTO y (c1) VALUES (35444.21)
INSERT INTO y (c1) VALUES (35444.79)
SELECT
CASE WHEN c1 IS NULL THEN 0 ELSE c1 END
FROM y
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1174942335.112146.304030@.n59g2000hsh.googlegr oups.com...
> Plus, I would like to know why SQL Server is rounding that value. To
> me this looks like a defect. It should not be rounding the value.
>
|||The problem is in the last two writes in the example I gave.
Hopefully this explains it more...Run this code to create table Z.
Run this:
CREATE TABLE z(c1 varchar(15))
INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE y.c1
END FROM y
Here is what ends up in z for me:
0
123.45
555.7
35444.2
35444.8
The last two records get rounded to one decimal place. Why does that
happen? When I cast it as money, the values do not round:
INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE
CAST(y.c1 AS Money) END FROM y
0.00
123.45
555.70
35444.21
35444.79
But now the '0' is '0.00'. Which is NOT what I want.
|||I really don't know why SQL Server would cast the float values that way. In general, I avoid float
being what sometime is called an approximate datatype. So, it seems that when SQL Server converts
from float to varchar, you see some funny things. I would suggest you cast to something else, like
decimal And if you *really* want to do presentation logic in the engine, you can convert NULL to 0,
cast to varchar, then replace '0.00' with 0. See below:
INSERT INTO z ([c1])
SELECT CASE WHEN c = '0.00' THEN '0' ELSE c END
FROM
(
SELECT
CAST(
CAST(
ISNULL(y.c1, 0)
AS decimal (9,2))
AS varchar(15)) AS c
FROM y
) AS inr
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Paul" <pwh777@.hotmail.com> wrote in message
news:1175032433.780317.287070@.d57g2000hsg.googlegr oups.com...
> The problem is in the last two writes in the example I gave.
> Hopefully this explains it more...Run this code to create table Z.
> Run this:
> CREATE TABLE z(c1 varchar(15))
> INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE y.c1
> END FROM y
> Here is what ends up in z for me:
> 0
> 123.45
> 555.7
> 35444.2
> 35444.8
> The last two records get rounded to one decimal place. Why does that
> happen? When I cast it as money, the values do not round:
> INSERT INTO z ([c1]) SELECT CASE WHEN y.c1 IS NULL THEN '0' ELSE
> CAST(y.c1 AS Money) END FROM y
> 0.00
> 123.45
> 555.70
> 35444.21
> 35444.79
> But now the '0' is '0.00'. Which is NOT what I want.
>
|||Thanks Tibor! That was helpful.