SQL Query Finding From Table DataType Declaration - sql

I got some serial keys to find in sql database, such as “A-B-C”,”D-E-F”,”G-H-I”,”J-K-L” and they are stored in tblTemp using ntext data type. These above keys may store in three columns, colA, colB and colC (sometimes store in one column and the rest are null). Sometimes, two serial keys can find in one column (e.g. A-B-C;D-E-F) using “;” seperated. so i wrote the following sql query.
Declare #sa TABLE(var1 nvarchar(Max));
Insert INTO #sa(var1) VALUES (N’A-B-C’);
Insert INTO #sa(var1) VALUES (N’D-E-F’);
Insert INTO #sa(var1) VALUES (N’G-H-I’);
Insert INTO #sa(var1) VALUES (N’J-K-I’);
SELECT * FROM tblTemp
WHERE colA IN (SELECT var1 FROM #sa);
so i got the following error message.
The data types ntext and nvarchar(max) are incompatible in the equal to operator.
I still need to find for colB and colC. How should write query for this kind of situation?
all suggestions are welcome.

CAST/CONVERT (msdn.microsoft.com) your var1 to NTEXT type in your query so that the types are compatible.
SELECT
*
FROM
tblTemp
WHERE
colA IN (
SELECT
CAST(var1 AS NTEXT)
FROM
#sa
);

You have to convert/cast your search term as an appropriate data type, in this case text.
Try this:
Declare #sa TABLE(var1 nvarchar(Max));
Insert INTO #sa(var1) VALUES (N’A-B-C’);
Insert INTO #sa(var1) VALUES (N’D-E-F’);
Insert INTO #sa(var1) VALUES (N’G-H-I’);
Insert INTO #sa(var1) VALUES (N’J-K-I’);
SELECT *
FROM tblTemp t
WHERE EXISTS (SELECT 1
FROM #sa s
WHERE t.colA like cast('%'+s.var1+'%' as text)
OR t.colB like cast('%'+s.var1+'%' as text)
OR t.colC like cast('%'+s.var1+'%' as text)
);

Since all suggestions are welcome.
How about change the datatype on tblTemp to NVARCHAR(MAX)?
NTEXT was deprecated with the introduction of NVARCHAR(MAX) in 2005.
ALTER TABLE tblTemp ALTER COLUMN colA NVARCHAR(MAX)

Related

'LIKE' issues with FLOAT: SQL query needed to find values >= 4 decimal places

I have a conundrum....
There is a table with one NVARCHAR(50) Float column that has many rows with many numbers of various decimal lengths:
'3304.063'
'3304.0625'
'39.53'
'39.2'
I need to write a query to find only numbers with decimal places >= 4
First the query I wrote was:
SELECT
Column
FROM Tablename
WHERE Column LIKE '%.[0-9][0-9]%'
The above code finds all numbers with decimal places >= 2:
'3304.063'
'3304.0625'
'39.53'
Perfect! Now, I just need to increase the [0-9] by 2...
SELECT
Column
FROM Tablename
WHERE Column LIKE '%.[0-9][0-9][0-9][0-9]%'
this returned nothing! What?
Does anyone have an explanation as to what went wrong as well and/or a possible solution? I'm kind of stumped and my hunch is that it is some sort of 'LIKE' limitation..
Any help would be appreciated!
Thanks.
After your edit, you stated you are using FLOAT which is an approximate value stored as 4 or 8 bytes, or 7 or 15 digits of precision. The documents explicitly state that not all values in the data type range can be represented exactly. It also states you can use the STR() function when converting it which you'll need to get your formatting right. Here is how:
declare #table table (columnName float)
insert into #table
values
('3304.063'),
('3304.0625'),
('39.53'),
('39.2')
--see the conversion
select * , str(columnName,20,4)
from #table
--now use it in a where clause.
--Return all values where the last digit isn't 0 from STR() the conversion
select *
from #table
where right(str(columnName,20,4),1) != 0
OLD ANSWER
Your LIKE statement would do it, and here is another way just to show they both work.
declare #table table (columnName varchar(64))
insert into #table
values
('3304.063'),
('3304.0625'),
('39.53'),
('39.2')
select *
from #table
where len(right(columnName,len(columnName) - charindex('.',columnName))) >= 4
select *
from #table
where columnName like '%.[0-9][0-9][0-9][0-9]%'
One thing that could be causing this is a space in the number somewhere... since you said the column type was VARCHAR this is a possibility, and could be avoided by storing the value as DECIMAL
declare #table table (columnName varchar(64))
insert into #table
values
('3304.063'),
('3304. 0625'), --notice the space here
('39.53'),
('39.2')
--this would return nothing
select *
from #table
where columnName like '%.[0-9][0-9][0-9][0-9]%'
How to find out if this is the case?
select *
from #table
where columnName like '% %'
Or, anything but numbers and decimals:
select *
from #table
where columnName like '%[^.0-9]%'
The following is working fine for me:
declare #tab table (val varchar(50))
insert into #tab
select '3304.063'
union select '3304.0625'
union select '39.53'
union select '39.2'
select * from #tab
where val like '%.[0-9][0-9][0-9][0-9]%'
Assuming your table only has numerical data, you can cast them to decimal and then compare:
SELECT COLUMN
FROM tablename
WHERE CAST(COLUMN AS DECIMAL(19,4)) <> CAST(COLUMN AS DECIMAL(19,3))
You'd want to test the performance of this against using the character data type solutions that others have already suggested.
You can use REVERSE:
declare #vals table ([Val] nvarchar(50))
insert into #vals values ('3304.063'), ('3304.0625'), ('39.53'), ('39.2')
select [Val]
from #Vals
where charindex('.',reverse([Val]))>4

How to validate/restrict values in a column as per a specific format in a sql Database

I am working on an application that populates values from sql Database in a format two numeric and alpha character e.g 11G,34H. There is no validation or check for the same.I want to put put checkpoint/validation from Database end.Is it possible to implement via SQL procedure or anything.Can anyone help me with the code.
Try the below query
DECLARE #strtable TABLE (column1 VARCHAR(50))
INSERT INTO #strtable
VALUES ('11H'),('sda'),('175HH'),('1H1'),('282')
INSERT INTO YourTable (Column1)
SELECT Column1
FROM #strtable
WHERE LEN(column1)=3
AND ISNUMERIC(LEFT(column1,2))=1
AND ISNUMERIC(RIGHT(column1,1))!=1
--Output : 11H

SQL automatically rounding off values

I have two table. First table(Table1) use to get the records and second table(Table2) used to insert first table record into it. But I am little bit confused after getting result.
In table 1 and table 2 column "Amount" have same data type i.e nvarchar(max)
Table1
Id Amount
1 Null
2 -89437.43
2 -533.43
3 22403.88
If I run this query
Insert into Table2(Amount)
Select Amount from Table1
Then get result like this, I don't know why values are automatically rounded off
Table2
Id Amount
1 Null
2 -89437.4
2 -533.43
3 22403.9
SQL Server will round float values when converting back and to from string types.
And then you have the fun bits of empty string being 0, as well other strange effects
SELECT CAST(CAST('' AS float) AS nvarchar(MAX))
SELECT CAST(CAST('0.E0' AS float) AS nvarchar(MAX))
Use decimal.
If you need to store "blank" (how does this differ from NULL?) use a separate bit column to allow that extra value
Here is good explanation about your question.
Eigher you explicitly give float or decimal or numeric(xx,x) (x means numeric value)
Then it will convert as the data, other wise it round off the last value.
Insert into Table2(Amount)
Select cast(Amount as numeric(18,2) --or , cast (Amount as float)
from Table1
Check this link:-
TSQL Round up decimal number
In my case I was doing the conversion to the correct data type but had decimal(18,0) for the column in the table. So make sure the decimal places are represented properly for the column decimal(18,2).
Perhaps it's your query tool that's truncating to 8 characters.
Check the actual fields lengths to see if the problem is really in the database:
SELECT LEN(Amount)
FROM Table2
WHERE Amount LIKE '%-89437.%'
Unreproducible. Running this script on SQL Server 2012:
DECLARE #T1 TABLE ([Amount] nvarchar(max) NULL);
DECLARE #T2 TABLE ([Amount] nvarchar(max) NULL);
INSERT INTO #T1 ([Amount])
VALUES (NULL),('-89437.43'),('-533.43'),('22403.88');
Insert into #T2(Amount)
Select Amount from #T1;
SELECT * FROM #T2;
Produces this result:
Amount
NULL
-89437.43
-533.43
22403.88
The problem you describe does not exist.
This will show you the problem:
DECLARE #T1 TABLE ([Amount123456789] money NULL);
DECLARE #T2 TABLE ([Amount123456789] nvarchar(max) NULL);
INSERT INTO #T1 ([Amount123456789])
VALUES (NULL),('-89437.43123'),('-533.43456'),('22403.88789'),(22403.88789);
Insert into #T2(Amount123456789)
Select Amount123456789 from #T1;
SELECT * FROM #T1;
SELECT * FROM #T2;

Inserting "bad" data into a SQL database?

I'm writing a query that inserts customer data into a MSSQL database. Very basic.
Unfortunately, I ran into a problem when trying to do the following:
INSERT INTO USERS(newid(),'BOB''S SELECT MARKETING')
I made sure to escape my quotes, but the server is still seeing SELECT as a reserved keyword. I don't want to have to wrap a bunch of reserved words in brackets. Is there a cleaner way of getting my data in the database intact and not mangled by brackets?
I appreciate your help.
Thank you!
You are missing the Key word VALUES:
INSERT INTO USERS VALUES (NEWID(),'BOB''S SELECT MARKETING');
You have several choices of syntax here. Using the one in your code sample, you forgot the VALUES keyword. For example:
declare #users table
(
id uniqueidentifier,
name varchar(50)
)
insert into #users values (newid(), 'BOB''S SELECT MARKETING')
You can also use the insert into / select statement like below if you are inserting a value into each one of the table's columns:
declare #users table
(
id uniqueidentifier,
name varchar(50)
)
insert into #users
select newid(), 'BOB''S SELECT MARKETING'
Or you can use the insert into / select statement and specify the columns you are inserting:
declare #users table
(
id uniqueidentifier,
name varchar(50)
)
insert into #users (id, name)
select newid(), 'BOB''S SELECT MARKETING'

Double columns in a SQL View

We have a legacy interface that inserts into table T1 that values "BODY_TEXT" (varcharmax), "BODY_BIN"(varbinarymax).
It currently inserts just to one of the columns, and leave the other one NULL.
Now we implemented a new interface - table T2 that has only "BODY"(varbinarymax) column.
I need to create a view V1 that should replace T1, meaning
CREATE VIEW V1 AS
SELECT
T2.UNIQUE_ID AS UNIQUE_ID,
etc…
Now I don't know how to treat T2.BODY column… I need to do something like
T2.BODY AS (whatever is not null(BODY_BIN, BODY_TEXT)). It must also support varcharmax vs. varbinarymax.
I tried implementing COALESCE meaning T2.BODY AS COALESCE(BODY_BIN, BODY_TEXT) but it doesn't work.
Nor does
COALESCE(BODY_BIN, BODY_TEXT) AS BODY
T2.BODY AS BODY
Again - In the legacy table we had T1 with two columns - BODY_BIN and BODY_TEXT. The user inserted one value and left the other one null, since body is either binary or textual but not both. The new interface has a table T2 that has only one column, BODY (varbinarymax), and I was asked to delete table T1 and create a view with the same name. Meaning in order to preserve backward comparability they should still be able to perform "insert into T1 values X,Y" (X is DATA_BIN or NULL, and Y is DATA_TEXT or NULL), but the content (taken from either X or Y) should be translated into ONE column in the T2 table - BODY.
I have no idea how to pull this one up.
Can you help me?
Thanks,
Nili
varbinary to varchar (note the order) will cast implicitly. So this works because ISNULL takes the first datatype
ISNULL(varchar, varbinary)
COALESCE fails because it takes the highest precedence datatype (which is varbinary). The implicit cast is not allowed. ISNULL(varbinary, varchar) would fail too
You need an explicit CAST
DECLARE #foo TABLE (ID int IDENTITY (1,1), charmax varchar(MAX) NULL, binmax varbinary(MAX) NULL)
INSERT #foo (charmax, binmax) VALUES ('text', NULL)
INSERT #foo (charmax, binmax) VALUES (NULL, 0x303131)
INSERT #foo (charmax, binmax) VALUES ('Moretext', NULL)
INSERT #foo (charmax, binmax) VALUES (NULL, 0x414243454647)
SELECT ISNULL(binmax, CONVERT(varbinary(MAX), charmax))
FROM #foo
or
SELECT COALESCE(binmax, CONVERT(varbinary(MAX), charmax))
FROM #foo
Edit: I understand the question now... maybe
DECLARE #foo2 TABLE (ID int IDENTITY (1,1), BODY varbinary(MAX) NULL)
INSERT #foo2 (BODY) VALUES (CAST('text' AS varbinary(MAX)))
INSERT #foo2 (BODY) VALUES (0x303132)
INSERT #foo2 (BODY) VALUES (CAST('Moretext' AS varbinary(MAX)))
INSERT #foo2 (BODY) VALUES (0x414243454647)
SELECT
BODY AS BODY_BIN,
CAST(BODY AS varchar(MAX)) AS BOY_TEXT
FROM
#foo2
Edit2: something like this (not tested) to maintain the same write interface. Normally, I'd only maintain a read interface hence the confusion...
CREATE VIEW OldFoo
AS
SELECT
ID,
BODY AS BODY_BIN,
CAST(BODY AS varchar(MAX)) AS BOY_TEXT
FROM
newFoo
GO
CREATE TRIGGER ON OldFoo INSTEAD OF INSERT
AS
SET NOCOUNT ON
INSERT newFoo (BODY)
SELECT ISNULL(binmax, CONVERT(varbinary(MAX), charmax))
FROM INSERTED
GO
First, this is a bad design. Joining on a varchar(max) or varbinary(max) field is a bad idea since they can't be indexed. Prepare for table scans!
You have inconsistent data types in the same column, which is a problem.
Try:
CAST((COALESCE(BODY_BIN, BODY_TEXT)) as varchar(max))