Using BETWEEN on a varchar field not a numeric field? - sql

I am using ColdFusion 8 and SQL Server 2008 R2.
I am trying to query a column of values to get rows with a value within a range. The column SHOULD be numeric, but it's not. It's setup as a varchar (by someone else). There are 100,000+ rows of data. Here's a FAKE sample of the data:
ID COLUMN
1 1
2 1.2
3 0.9
4 5
5 -6
My query looks like this:
select column
from table
where column between 1 and 2
This query won't run because the where statement's column is a varchar, and I get a conversion error, so I have to change the where statement to this:
where column between '1' and '2'
Now, when I run a query like this, it runs, but I don't get results. But I know that I should be seeing results, because I know that many of the values in the column field are within that range I am querying.
I am wondering if I am seeing no results due to the field being a varchar and not a numeric. Might that be messing up my results?
Also, we have 100,000+ records we are searching through, would there be a big performance hit by using a varchar field instead of a numeric field?

You need to CAST the results WHERE ISNUMERIC(column) = 1 AND CAST(column AS decimal(10,5)) BETWEEN 1 AND 2 for example.

One more option
Implicit transformation is carried out nvarchar() into numeric()
Cost of operations obvious and implicit transformation equals, but code a little bit it is less;))
Predicate
SELECT *
FROM dbo.your_table
WHERE [COLUMN] BETWEEN 1.00 AND 2.00

Related

The data types in each column don't need to be compatible between the UNION queries

I read here that to be able to use SQL UNION queries,
data types in each column must be compatible between the individual queries.
So select a, b from table1 UNION select c, d from table2, for this query to work, we need a and c data types to be compatible.
However, when I try to test that, and make table users having two columns (id int, name varchar(15)), and table calc having two values (x int, y int), and after inserting elements
(1, 'saad') into table users, and values (3, 5) into table calc, and try query select * from users union select * from calc;, it shows the results as follows without any errors:
1 | saad
3 | 5
although name and y data types is not compatible, and was supposed to cause error
Conversion failed when converting the int value 5 to data type varchar
I thought it may be browser specific behavior, so I tried this also in google chrome, but it worked without any errors also!
Can someone explain to me why?
Thanks in advance.
Edit:
I'm using MySql 5.6
With MS SQL, there's a distinction between UNION and UNION ALL.
In the case of a UNION query, each value is compared to every other value for that column across all of select clauses. This might result in fewer records in final result than exist in the original select clause results. Even if you didn't intend for it, the optimizer will compare values from a and c along with b and d to find the uinion of those two sets. That also means that the datatype if they're different goes through an implicit data conversion to sql_variant to accomplish the goal of the union request.
Since UNION ALL is just stacking the sets one on top of each other, there's less of a need to compare the values.

Access Queries doesn't get all the required records

I've imported a table from Microsoft excel and when i use query to get the required range of records using Between function, when i enter 1 and 20 the records with the value 2-9 aren't returned, or 10 and 200 11-99 aren't returned!
It is most likely because the data type of the column is defined as Text. When you have a text value access uses a text based order to lookup for the values. What you need to do is to convert the value to number, like this:
SELECT col1, col2
from Table1
WHERE Val(col1) BETWEEN 1 AND 20
But the better solution will be to fix you table structure so that the numeric values are stored in the numeric data types

MS SQL Server Zero Padding

EDIT:
I'm changing column datatype to Varchar, should suggestion work, answer will be upvoted
Full Story:
I receive data for a person with an associated temporary number for every person that is 5 digits long, I process this information and then send variables to a stored procedure that handles the inserting of this data. When sending the variables to the stored procedure I appear to be losing any prefixed 0's.
For example:
Number sent to stored Proc - Number actually inserted column
12345 - 12345
01234 - 1234
12340 - 12340
This only appears to be happening for numbers with a 0 in front. Meaning if I received:
00012 it would insert as 12
Is there a way where I could either update the column to always 0 pad to the left by a fixed number, meaning if we got 12 it would automatically make the value 00012.
OR
Is there a way to do this with the variable when its received by the stored procedure before the variable is inserted into the table.
Something along the lines of:
SET #zeroPaddedFixedNum = LeftPad(#numberRecieved, '0', 5);
Additionally, I now need to stop any more numbers from inserting and update all current incorrectly lengthed numbers. Any suggestions?
Perhaps it's just my Google ability that has failed but I have tried searching numerous pages.
For this, the column should be of varchar datatype. You can then do this
Insert into table(col)
select right('00000'+cast(#var as varchar(5)),5)
EDIT : To update existing data
Update table
set col=right('00000'+cast(col as varchar(5)),5)
where len(col)<5
As pointed out, you'll have to use VARCHAR(5) for your needs... But I would not change the columns type, if the values stored are numbers actually. Rather use one of the following, whenever you pass these values to your SP (You might use a computed column or a VIEW though).
Try
SELECT REPLACE(STR(YourNumber,5),' ','0');
The big advantage: In cases, where your number exceeds 5 digits, this would return *****. It is better to get an error than to get wrong numbers... Other approaches with RIGHT() might truncate your result unpredictably.
With SQL Server 2012 you should use FORMAT()
SELECT FORMAT(YourNumber,'00000')

Conversion failing when changing join constraint from list of varchars to subquery

I'm trying to update a procedure we run by switching out a list of static varchars within an IN statement (which is in a join condition) to use a subquery instead. However, I'm getting an error saying Conversion failed when converting the varchar value 'Normal' to data type int.
I know that means somewhere in the query I'm trying to convert the value 'Normal' to an int, but in this query there's not a place where anything should be an int - it's all varchar or datetime, and the subquery returns the same values as the former static list of varchars. Furthermore, there's not a place anywhere in my dataset with the value "Normal", which is what really confuses me.
Has anyone else dealt with something like this before?
EDIT:
Here's the code (reduced to just show the pieces that are causing the error):
select * from #tempTable
left join dbo.v_Lookup_Assumptions Assumptions on
case when Group3 in
--('Value1', 'Value2', 'Value3')
(Select lookupdetail_name from lookupDetail)
then Group3 else Group2 end =Assumptions.Sector2
and AsOfDate between Assumptions.StartDate and Assumptions.EndDate
and ShortName = Assumptions.AssumptionShortName
I can comment out the subquery and uncomment the list of values and it works. Also, if I don't run the "ShortName" constraint when I'm using the subquery, it works (though doesn't give the expected results, as you might expect). All join constraints are either varchar or date.
In addition, I added 'Normal' to the list of static values and it ran as expected. I also updated the subquery to SELECT 'Value1' from lookupDetail and it failed.
EDIT2:
And this makes no sense, but if I limit the original #tempTable to 2080 records, the new subquery syntax works. However, if I let it go to 2081 records it fails - regardless of the dataset. In other words, as I change the dates around so I get different data each time through and limit #tempTable to 2080 records, this new syntax works just fine. Change it to 2081 records and it fails. If I run through the 2081 record dataset and filter with a WHERE clause, I can get every row in the 2081 record to display as long as it's not all 2081 at the same time.
It turns out the execution plan was changing when the total number of records would exceed 2080, and was implicitly converting a varchar field to an int. I grabbed the XML query plan for the small dataset from SQL Server Profiler and forced the larger dataset query to use it with OPTION (USE PLAN '<Insert XML Query Plan Here />').

UNION causes "Conversion failed when converting the varchar value to int"

I tried to search for previous articles related to this, but I can't find one specific to my situation. And because I'm brand new to StackOverflow, I can't post pictures so I'll try to describe it.
I have two datasets. One is 34 rows, 1 column of all NULLs. The other 13 rows, 1 column of varchars.
When I try to UNION ALL these two together, i get the following error:
Conversion failed when converting the varchar value to data type int.
I don't understand why I'm getting this error. I've UNIONed many NULL columns and varchar columns before, among many other types and I don't get this conversion error.
Can anyone offer suggestions why this error occurs?
The error occurs because you have corresponding columns in the two of the subqueries where the type of one is an integer and the type of the other is a character. Then, the character value has -- in at least one row -- a value that cannot be automatically converted to an integer.
This is easy to replicate:
select t.*
from (select 'A' as col union all
select 1
) t;
Here is the corresponding SQL Fiddle.
SQL Server uses pretty sophisticated type precedence rules for determining the destination type in a union. In practice, though, it is best to avoid using implicit type conversions. Instead, explicitly cast the columns to the type you intend.
EDIT:
The situation with NULL values is complicated. By itself, the NULL value has no type. So, the following works fine:
select NULL as col
union all
select 'A';
If you type the NULL, then the query will fail:
select cast(NULL as int) as col
union all
select 'A';
Also, if you put SQL Server in a position where it has to assign a type, then SQL Server will make the NULL an integer. Every column in a table or result set needs a type, so this will also fail:
select (select NULL) as col
union all
select 'A';
Perhaps your queries are doing something like this.
I have also encountered this error when I accidentally had the fields out of sequence in the 2 SELECT queries that I was unioning. Adjusting the fields' sequence fixed the problem.