Error converting data type nvarchar to numeric. Tried convert and replace - sql-server

I am trying to add a sum of my forecast using a code
select
sum(cast(replace(replace(ZFREEGOOD, ',', ''), ' ', '') as decimal(22,8)))
from
TEMP_GBR_History_1611
I keep getting an error
Error converting data type nvarchar to numeric.
I used a case statement to figure out which rows failed. These are some of them
Would be of great help to get a solution

You're not handling the blank case, this works with test data:
select sum(cast(case when replace(replace(ZFREEGOOD,',',''),' ','') = '' then '0' else replace(replace(ZFREEGOOD,',',''),' ','') end as decimal(22,8))) from TEMP_GBR_History_1611

One option is to use try_convert(money,...) It tends to be a little more forgiving.
Example
Select AsMoney = try_convert(money,' 27,300') -- works!
,AsInt = try_convert(int,' 27,300')
,AsDec = try_convert(decimal(10,2),' 27,300')
,AsFloat = try_convert(float,' 27,300')
Returns
AsMoney AsInt AsDec AsFloat
27300.00 NULL NULL NULL

Related

SQL: how to do an IF check for data range parameters

I am writing a stored procedure that takes in 4 parameters: confirmation_number, payment_amount, start_range, end_range.
The parameters are optional, so I am doing a check in this fashion for the confirmation_number, and the payment_amount parameters:
IF (#s_Confirmation_Number IS NOT NULL)
SET #SQL = #SQL + ' AND pd.TransactionNumber = #s_Confirmation_Number'
IF (#d_Payment_Amount IS NOT NULL)
SET #SQL = #SQL + ' AND pd.PaymentAmount = #d_Payment_Amount'
I would like to ask for help because I am not sure what is the best method to check for the date range parameters.
If someone could give me en example, or several on how this is best achieved it would be great.
Thank you in advance.
UPDATE - after receiving some great help -.
This is what I have so far, I am following scsimon recommendation, but I am not sure about the dates, I got the idea from another post I found and some playing around with it. Would you care looking at it and tell me what you all think?
Many thanks.
#s_Confirmation_Number NVARCHAR(50) = NULL
, #d_Payment_Amount DECIMAL(18, 2) = NULL
, #d_Start_Range DATE = NULL
, #d_End_Range DATE = NULL
...
....
WHERE
ph.SourceType = #s_Source_Type
AND ((pd.TransConfirmID = #s_Confirmation_Number) OR #s_Confirmation_Number IS NULL)
AND ((pd.PaymentAmount = #d_Payment_Amount) OR #d_Payment_Amount IS NULL)
AND (((NULLIF(#d_Start_Range, '') IS NULL) OR CAST(pd.CreatedDate AS DATE) >= #d_Start_Range)
AND ((NULLIF(#d_End_Range, '') IS NULL) OR CAST(pd.CreatedDate AS DATE) <= #d_End_Range))
(The parameter sourceType is a hard-coded value)
This is called a catch all or kitchen sink query. It is usually written as such:
create procedure myProc
(#Payment_Amount int = null
,#Confirmation_Number = null
,#start_range datetime
,#end_range datetime)
as
select ...
from ...
where
(pd.TransactionNumber = #Confirmation_Number or #Confirmation_Number is null)
and (pd.PaymentAmount = #Payment_Amount or #Payment_Amount is null)
The NULL on the two parameters gives them a default of NULL and makes them "optional". The WHERE clause evaluates this to only return rows where your user input matches the column value, or all rows when no user input was supplied (i.e. parameter IS NULL). You can use this with the date parameters as well. Just pay close attention to your parentheses. They matter a lot here because we are mixing and and or logic.
Aaron Bertrand has blogged extensively on this.
I do it like this
WHERE
COALESCE(#s_Confirmation_Number,pd.TransactionNumber) = pd.TransactionNumber AND
COALESCE(#d_Payment_Amount,pd.PaymentAmount) = pd.PaymentAmount
If we have a value for each of these parameters then it will check against the filter value otherwise it will always match the filter value if the parameter is null.
I've found that using COALESCE is faster and clearer than IF control statements or using OR in the WHERE clause.
There is another way.
But I tested and realized that a scsimon query is faster than mine.
AND (CASE
WHEN #Confirmation_Number is not null
THEN (CASE
WHEN pd.TransactionNumber = #Confirmation_Number
THEN 1
ELSE 0
END)
ELSE 1
END = 1)

Select with Contains parameter not working with null

With my select below, if blank string is passed in I get the following error: Null or empty full-text predicate
in my DBAdapter when fetching rows from the database. If I provide a value, such as Well, I do not get results when I should as Well is in the r.[Desc] column. If I pass in Well One, I get: Syntax error near 'one' in the full-text search condition 'Well one'.
If I pass in One, I get nothing.
I've read similar questions here and have not seen a pattern where the value passed in can be nothing, the beginning of the column data, a word in the middle of the column data or more than one word in any order of the column data. I thought Contains returns the row if the column contains the value or part of the value passed in.
What am I doing wrong?
if #Drawing = ''
set #Drawing = null
if #ItemName = ''
set #ItemName = null
if #CF3 = ''
set #CF3 = null
if #Desc = ''
set #Desc = null
if #Design = ''
set #Design = null
if #MaxPSI = 0
set #MaxPSI = null
Select distinct
,r.[DRAWING]
,r.[DESC]
,r.[OP_PSI]
,r.[MAX_PSI]
,r.[MAX_TEMP]
,r.[Insulated]
,r.[DESIGN]
From Ref r
inner join Eng e on e.[DRAWING] = r.[DRAWING]
where r.SurveyNumber = #SurveyNumber
And (rtrim(#Drawing) is NUll or rtrim(r.DRAWING) like rtrim(#Drawing) + '%')
And (rtrim(#Design) is NUll or rtrim(r.DESIGN) like rtrim(#Design) + '%')
And (rtrim(#MaxPSI) is NUll or rtrim(r.MAX_PSI) like rtrim(#MaxPSI) + '%')
And (rtrim(#CF3) is NUll or rtrim(e.CF3) like rtrim(#CF3) + '%')
And (rtrim(#ItemName) is NUll or rtrim(e.ITEM_NAME) like rtrim(#ItemName) + '%')
AND ((#Desc = '""') OR CONTAINS( (r.[Desc]), #Desc))
I think you can try checking for empty as follows:
AND ((#Desc = '""' OR #Desc = '') OR CONTAINS( (r.[Desc]), #Desc))
I suspect the empty predicate may be getting passed as '' instead of "".
Have not used Contains much but from section in the doc [here][1] it seems you either need operators between the words or need to wrap expression in double quotes "". So what you can do is try passing params like this:
AND ((#Desc = '""' OR #Desc = '') OR CONTAINS( (r.[Desc]), '"'+#Desc+'"'))
What possible purpose is
rtrim(#Drawing) is NUll
If it is NULL the rtrim has no meaning. Besides comparison of string basically does an rtrim.

replace not working after specific number

I have a table with a column vouchn. The recod of this column eg-if it receipt voucher it will record like RV103 AND LIKE payment it stores like PV99. I also use this sql for gettin max records.
SELECT MAX(REPLACE(vouchn, 'RV', '')) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')
it is ok until i reach RV999. After then even record RV1000 is there the above sql retrieve RV999. What is the error of the above code.
If REPLACE(vouchn, 'RV', '') always return numeric result, you can as the below:
SELECT MAX(REPLACE(vouchn, 'RV', '') * 1) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')
Add CONVERT to numeric type:
SELECT MAX(CONVERT(BIGINT,REPLACE(vouchn, 'RV', ''))) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')

Query fails on "converting character string to smalldatetime data type"

I've been tasked with fixing some SQL code that doesn't work. The query reads from a view against a predicate. The query right now looks like so.
SELECT TOP (100) Beginn
FROM V_LLAMA_Seminare
//Removal of the following line makes the query successful, keeping it breaks it
where Beginn > (select cast (getdate() as smalldatetime))
order by Beginn desc
When I run the above query, I am greeted with the following error.
Msg 295, Level 16, State 3, Line 1
Conversion failed when converting character string to smalldatetime data type.
I decided to remove the WHERE clause, and now it runs returning 100 rows.
At first, I thought that behind the scenes, SQL Server was somehow including my predicate when bringing back the View . But then I investigated how the View was being created, especially the Beginn field, and at no point does it return a String.
Long story short, the column that becomes the Beginn field is a BIGINT timestamp like 201604201369.... The original user transforms this BIGINT to a smalldatetime using the following magic.
....
CASE WHEN ma.datum_dt = 0
THEN null
ELSE CONVERT(smalldatetime, SUBSTRING(CAST(ma.datum_dt AS varchar(max)),0,5) + '-' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),5,2) + '-' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) + ' ' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),9,2) +':'+
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),11,2) +':' +
RIGHT(CAST(ma.datum_dt AS varchar(max)),2)) END AS Beginn
...
My last attempt at finding the problem was to query the view and run the function ISDATE over the Beginn column and see if it returned a 0 which it never did.
So my question is two fold, "Why does a predicate break something" and two "Where on earth is this string error coming from when the Beginn value is being formed from a BIGINT".
Any help is greatly appreciated.
This problem is culture related...
Try this and then change the first SET LANGUAGE to GERMAN
SET LANGUAGE ENGLISH;
DECLARE #bi BIGINT=20160428001600;
SELECT CASE WHEN #bi = 0
THEN null
ELSE CONVERT(datetime, SUBSTRING(CAST(#bi AS varchar(max)),0,5) + '-' +
SUBSTRING(CAST(#bi AS varchar(max)),5,2) + '-' +
SUBSTRING(CAST(#bi AS varchar(max)),7,2) + ' ' +
SUBSTRING(CAST(#bi AS varchar(max)),9,2) +':'+
SUBSTRING(CAST(#bi AS varchar(max)),11,2) +':' +
RIGHT(CAST(#bi AS varchar(max)),2)) END AS Beginn
It is a very bad habit to think, that date values look the same everywhere (Oh no, my small application will never go international ...)
Try to stick to culture independent formats like ODBC or ISO
EDIT
A very easy solution for you actually was to replace the blank with a "T"
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) + 'T' +
Then it's ISO 8601 and will convert...
The solution was found after looking through #Shnugo's comment. When I took my query which contained the Bigint->Datetime conversion logic, and put it into a CTE with "TOP 100000000" to avoid any implicit conversion actions, my query worked. Here is what my view looks like now with some unimportant parts omitted.
---Important part---
CREATE VIEW [dbo].[V_SomeView] AS
WITH CTE AS (
SELECT TOP 1000000000 ma.id AS MA_ID,
---Important part---
vko.extkey AS ID_VKO,
vko.text AS Verkaufsorganisation,
fi.f7000 AS MDM_Nr,
vf.f7105 AS SAPKdnr,
CASE WHEN ma.datum_dt = 0 --Conversion logic
CASE WHEN ma.endedatum_dt = 0 --Conversion logic
CONVERT(NVARCHAR(MAX),art.text) AS Art,
.....
FROM [ucrm].[dbo].[CRM_MA] ma,
[ucrm].[dbo].[CRM_fi] fi,
[ucrm].[dbo].[CRM_vf] vf,
[ucrm].[dbo].[CRM_ka] vko,
[ucrm].[dbo].[CRM_ka] art,
[ucrm].[dbo].[CRM_ka] kat
where ma.loskz = 0
and fi.loskz = 0
and vf.loskz = 0
and fi.F7029 = 0
and vf.F7023 = 0
...
GROUP BY ma.id,
vko.extkey,
vko.text,
fi.f7000 ,
vf.f7105,
ma.datum_dt,
ma.endedatum_dt,
....
)
select * FROM CTE;

How can I add text to my column's select statement

I want to prepend text to sql select,
I can do this:
SELECT (1328724983-time)/60/60 AS status
FROM voting
WHERE account = 'ThElitEyeS' AND vid = 1
This will show time left.
What I'd like to do is this though:
SELECT 'Please try after' + (1328724983-time)/60/60 AS status
FROM voting
WHERE account = 'ThElitEyeS' AND vid = 1
Is there any way I can accomplish this?
Just use cast or convert to convert it all to varchar for instance.
SELECT 'Please try after' + CAST((1328724983-time)/60/60 as varchar(80)) AS status
FROM voting
WHERE account = 'ThElitEyeS' AND vid = 1;
See the MSDN on Cast / Convert
Based on your comments you can do:
SELECT 'Please try again after' + CAST(MyColForHours as varchar(25)) + ' hours', AnyOtherColumns FROM Table
Was trying this today and getting an error
SQL0420N Invalid character found in a character string argument of the function "DECFLOAT". SQLSTATE=22018
Apparently we now need to use || instead of + to join the sections.
http://www-01.ibm.com/support/docview.wss?uid=swg21448700

Resources