SQL - Insert Into - Convert Datatype - sql

my table consists of the following fields:
IDTemp int NO NULL
Nr_ nvarchar(50) NULL
Description nvarchar(50) NULL
[Description 2] nvarchar(50) NULL
Price money NULL
Now I want to insert some values into that table from another database, unfortunately the price values from the other database are stored as a nvarchar and not a money value.
It looks a bit like this: 49.0000000000
If I insert this value into my money field, it stays empty.
My question is, how can I use INSERT INTO and convert my price value so that it goes into my money field and doesn't have 10 zeroes?
INSERT INTO TempSaveArticle (Nr_, Description, [Description 2], Price)
VALUES (123456789, Yarn, blue, '49.0000000000')
Thanks for your help in advance

Use CONVERT().
INSERT INTO TempSaveArticle (Nr_, Description, [Description 2], Price)
VALUES (123456789, Yarn, blue, CONVERT(MONEY, 49.0000000000))
Ideally you'd want to do this more dynamically.
INSERT INTO TempSaveArticle (Nr_, Description, [Description 2], Price)
SELECT myTable.*
FROM myTable
WHERE myTable.ID = 123 OR <<some other conditions>>
MONEY is effectively a DECIMAL.
You can CAST() or CONVERT() it to and from Decimal <--> Money. The only difference I know, is that MONEY is displayed by default using your computers' Language settings. But in my opinion, don't use MONEY, stick with DECIMALS and display it how you want using FORMAT(). More on this argument here.

use CAST to convert this properly
SELECT CAST ('49.0000000000' as numeric(10,2));
output :
49.00

We have to use cast or convert, this works directly for datatype CHAR, VARCHAR, NCHAR and NVARCHAR.
SQL server will not convert directly from TEXT to money. If the datatype is TEXT we have to first cast to varchar(for example) and then cast again to money.
NB: In some countries, for example France where I leave, it is standard practise to use a comma instead of a point. If there is a possibility of this we would need to use REPLACE first otherwise we will get an error.
create table mon (
monet text, monev nvarchar(20),
monetm money, monevm money);
GO
✓
insert into mon (monet, monev) values('49.0000000000','49.0000000000');
GO
1 rows affected
select * from mon;
GO
monet | monev | monetm | monevm
:------------ | :------------ | -----: | -----:
49.0000000000 | 49.0000000000 | null | null
update mon set monevm = cast(monev as decimal(20,10))from mon;
GO
1 rows affected
update mon set monetm = cast(monet as decimal(20,10))from mon;
GO
Msg 529 Level 16 State 2 Line 1
Explicit conversion from data type text to decimal is not allowed.
update mon set monetm = cast(
cast(monet as varchar)
as decimal(20,10))from mon;
GO
1 rows affected
select * from mon;
GO
monet | monev | monetm | monevm
:------------ | :------------ | ------: | ------:
49.0000000000 | 49.0000000000 | 49.0000 | 49.0000
db<>fiddle here

Related

Convert custom format string to Date

I'm receiving date values(as string) from one of the source system. It is always a 8 char long as shown below. I'm really not sure why they have kept in this format.
15/06-10
07/03-03
28/10-04
10/07-90
05/07-55
But for my application, I need to convert this into a proper date format(i.e. DD-MON-YYYY).
First 2 characters represent Date
Next 2 characters(after /) represent Month
last 2 represent year
In oracle, I can use to_date to achieve this. Something like
select to_date('15/06-10','yy/mm-dd') from dual;
But in SQL Server, I couldn't find such function. Is there a way to achieve this? The closest I have got is
DECLARE #d VARCHAR(100) = '15/06-10';
SELECT DATEFROMPARTS('20'+SUBSTRING(#d,7,2),SUBSTRING(#d,4,2),SUBSTRING(#d,1,2))
I'm not sure if this is the right way. Also It is giving the results only when I hardcode 20 for the year. But i'm getting data from 1950. So I cannot hardcode 19 or 20 Expected output for above sample is
+----------+-------------+
| 15/06-10 | 15-JUN-2010 |
+----------+-------------+
| 07/03-03 | 07-MAR-2003 |
+----------+-------------+
| 28/10-04 | 28-OCT-2004 |
+----------+-------------+
| 10/07-90 | 10-JUL-1990 |
+----------+-------------+
| 05/07-55 | 05-JUL-1955 |
+----------+-------------+
SQL Server does not have a to_date() function. But here is a simpler way to do the conversion you want:
select convert(date, replace('20' + str, '/', '-'))
from (values ('15/06-10'), ('07/03-03'), ('28/10-04')) v(str)
The expression in the select actually changes the format to YYYY-MM-DD, which is trivially converted to a date. However, SQL Server convert()/cast() is relatively smart about recognizing dates in strings.
One option uses datefromparts() and string functions:
select datefromparts(
'20' + left(#d, 2),
substring(#d, 4, 2),
right(#d, 2)
) as dt

query varchar field with date values

on sql-server db i need to query the dates > getdate from a varchar field
My table is like below ( activatioDate type is varchar(100)) :
id | activatioDate
22 | 12/3/2021
23 | 12/7/2019
24 | 12/9/2020
25 | 12/3/2019
26 | 12/11/2019
27 | 12/1/2024
my query
select * from mytable
where activatioDate > GETDATE()
Expected result
22 | 12/3/2021
24 | 12/9/2020
27 | 12/1/2024
I've got the following error
"The conversion of a varchar data type to a datetime data type resulted in an out-of-range value. "
Any suggestion?
You need to fix your design; that's the real problem here. Firstly, change the values to a unambiguous date/time format:
UPDATE dbo.YourTable
SET activatioDate = CONVERT(varchar(8),CONVERT(date,activatioDate,101),120);
Then you can ALTER the table:
ALTER dbo.YourTable ALTER COLUMN activatioDate date;
And then, finally, your query will work:
SELECT *
FROM dbo.YourTable
WHERE activatioDate > GETDATE();
Use CONVERT:
SELECT *
FROM mytable
WHERE CONVERT(datetime, activatioDate, 101) > GETDATE();
But in general you should avoid storing your dates as text in your SQL database.
Find all employees who didn't make any orders in the past 6 months. Tricky thing - the date field is varchar. You need to cast it to Date and apply Date functions

conversion varchar to int issues

The following query attempts to convert a varchar datatype to int -- but it's not working. Do you know why?
SELECT
CONVERT(INT, [BR]) AS dd,
CAST([BR] AS INT) AS cc
FROM
[Seg].[dbo].[pro_ben]
I get the error:
Msg 245, Level 16, State 1, Line 2
Conversion failed when converting the varchar value '3893.768' to data type int
Obviously your string has a decimal part, hence you cannot cast it directly to an integer.
A solution would be to first CAST to a floating point number, and then to an integer, like:
SELECT CAST( CAST([BR] AS FLOAT) AS INT) AS CC FROM [Seg].[dbo].[pro_ben]
Demo on DB Fiddle:
SELECT CAST('3893.768' AS FLOAT)
| (No column name) |
| ---------------: |
| 3893.768 |
SELECT CAST( CAST('3893.768' AS FLOAT) AS INT)
| (No column name) |
| ---------------: |
| 3893 |
The value is not an integer. This leaves you with various options:
You could use try_convert() which would return NULL.
You can use an intermediate data type and then convert to the final data type, but you might lose precision (under some circumstances).
You could convert to a numeric() instead.
Conversion to a numeric ignores decimal points, but they do not cause an error:
SELECT convert(numeric(10,0), [BR]) as dd
FROM [Seg].[dbo].[pro_ben];
You can then convert to an int if you specifically need that type.
I would try
Select Round([BR],0) as dd
FROM [Seg].[dbo].[pro_ben];
mmmm it appears once I change data type to float, it works.

Converting a 5 digit int into time

In a legacy system (SQL Server 2005) I have a column that stores a 5 digit integer (ie 86340) as time. The legacy application shows 86340 as 23:59:00. I am unsure how how to translate that 5 digit integer into a date-time data type using SQL.
SQL Server 2012+ has TIMEFROMPARTS function:
TIMEFROMPARTS ( hour, minute, seconds, fractions, precision )
Returns a time value for the specified time and with the specified precision.
Which is similiar to Excel's TIME:
TIME(hour, minute, second)
Excel version could handle values over 0-60 range:
Minute Required. A number from 0 to 32767 representing the minute. Any value greater than 59 will be converted to hours and minutes.
And SQL counterpart cannot do that.
It looks like that value is simply number of seconds so you could use:
DECLARE #A1 INT = 86340;
SELECT DATEADD(second, #A1,CAST('00:00:00' AS TIME));
DBFiddle Demo
EDIT:
As SQL Server 2005 does not support TIME data type, you could use DATETIME instead and skip date part in application.
DECLARE #A1 INT = 86340;
SELECT DATEADD(second, #A1,CAST('00:00:00' AS DATETIME));
DBFiddle Demo2
Since the value you have is an integer representation of the seconds since midnight, you have a couple of choices in SQL Server 2005. You can either render the value as a VARCHAR, which is readable, you can render it as DATETIME, which appends the date information, or you can maybe pull in a date from another field to get an meaningful DATETIME for your value.
SELECT CONVERT(VARCHAR(12), DATEADD(SECOND, 86340, 0), 114) AS [InVarchar];
+--------------+
| InVarchar |
+--------------+
| 23:59:00:000 |
+--------------+
SELECT DATEADD(SECOND, 86340, 0) AS [InDatetime];
+-------------------------+
| InDatetime |
+-------------------------+
| 1900-01-01 23:59:00.000 |
+-------------------------+
SELECT DATEADD(SECOND, 86340, CAST('2018-09-05' AS DATETIME)) AS [InDatetimeWithDate];
+-------------------------+
| InDatetimeWithDate |
+-------------------------+
| 2018-09-05 23:59:00.000 |
+-------------------------+
USE below query:
SELECT CONVERT(DATETIME, #Column_Name)
FROM Table;

SQL Server datetime in format yyyy-mm-ddThh:mi:ss.mmmZ

For an XML message I need SQL server 2008 R2 to select a set of dates in the following format:
yyyy-mm-ddThh:mi:ss.mmmZ
I searched Google and Stack Overflow a bit and came to the following solution:
SELECT STUFF(CONVERT(VARCHAR(50), CAST(GETDATE() AS DATETIMEOFFSET), 127),24,4,'')
This is working fine except for cases where the milliseconds of the date are "000". In such cases it selects NULL.
Can you please help me to find a solution that also works for dates where the milliseconds are "000"?
You can use the following piece of code to play around with:
declare #timestamps table (
i int,
timestamp datetime
)
insert into #timestamps (i, timestamp)
values
(1, '2017-09-13 01:00:00.003'),
(2, '2017-09-13 02:00:00.333'),
(3, '2017-09-13 03:00:00.000'),
(4, '2017-09-13 04:00:00')
select i, timestamp, STUFF(CONVERT(VARCHAR(50), CAST(timestamp AS DATETIMEOFFSET), 127),24,4,'') from #timestamps
From what I understand, you are using stuff() to get rid of the milliseconds beyond the third decimal place.
Instead you can just specify the precision of datetimeoffset as (3) instead of letting it default to (7):
select
i
, dto3 = convert(varchar(32),convert(datetimeoffset(3),timestamp),127)
, plusZ = convert(varchar(32),timestamp,127)+'Z' --without converting to datetimeoffset
-- /* SQL Server 2012+ */, tsFormat = format(timestamp,'yyyy-MM-ddTHH:mm:ss.fffZ')
from #timestamps
rextester demo: http://rextester.com/VKXBET35937
returns:
+---+--------------------------+--------------------------+
| i | dto3 | plusZ |
+---+--------------------------+--------------------------+
| 1 | 2017-09-13T01:00:00.003Z | 2017-09-13T01:00:00.003Z |
| 2 | 2017-09-13T02:00:00.333Z | 2017-09-13T02:00:00.333Z |
| 3 | 2017-09-13T03:00:00Z | 2017-09-13T03:00:00Z |
| 4 | 2017-09-13T04:00:00Z | 2017-09-13T04:00:00Z |
| 5 | 2017-09-13T14:12:34.567Z | 2017-09-13T14:12:34.567Z |
+---+--------------------------+--------------------------+
In SQL Server 2012+ the above works as well, though you could use format() if you wanted to always have 0s for milliseconds:
format(timestamp,'yyyy-MM-ddTHH:mm:ss.fffZ')
But format() can be slower, take a look here: format() is nice and all, but… - Aaron Bertrand
You may possible need to use the same code formatting but create a case statement for when milliseconds = 0