Using SUBSTRING with a column name - sql

I've been trying this all morning and can't find what I'm doing wrong. I have a string, 'XXYY0000' and I need the XX and YY seperatly.
So this works and gets the XX values:
SELECT LEFT(l.LOAN_MATURITY, 2)
FROM LOAN As l
But why is this not working when I need to get the YY values?
SELECT SUBSTRING(l.LOAN_MATURITY, 3, 2)
FROM LOAN As l
I researched and it should give the same output as the MID() function, but it gives me this error.
Msg 8116, Level 16, State 1, Line 1
Argument data type numeric is invalid for argument 1 of substring function.
Why is the data type important for the SUBSTRING function but not the LEFT function?

LEFT:
LEFT ( character_expression , integer_expression )
character_expression
Is an expression of character or binary data. character_expression can be a constant, variable, or column. character_expression can be of
any data type, except text or ntext, that can be implicitly converted
to varchar or nvarchar. Otherwise, use the CAST function to explicitly
convert character_expression.
SUBSTRING:
SUBSTRING ( expression ,start , length )
expression
Is a character, binary, text, ntext, or image expression.
With LEFT there is implicit CAST, with SUBSTRING not. You need to CAST it manually:
SELECT SUBSTRING(CAST(l.LOAN_MATURITY AS VARCHAR(100)), 3, 2)
FROM LOAN As l

Related

Remove all trailing decimal points from a number stored as a string

I have a couple of strings (nvarchar data type), one is a whole number and one has decimal points trailing. My goal is to remove decimals and have all values as a whole number.
I tried the code below but it gives me an error for the value with no decimals. Is there a way to accomplish this without a case expression. I'll be using this new column in a join.
SELECT [SOW]
--,LEFT([SOW], CHARINDEX('.', [SOW])-1) as 'TestColumn'
FROM [dbo].[t_Schedule_kdm]
WHERE sow in ('15229.11','11092')
Output:
11092
15229.11
My desired Output:
11092
15229
Just append a dot character so that you'll always find an index:
LEFT(SOW, CHARINDEX('.', SOW + '.') - 1)
It's not clear whether you need to cast the result of that expression to an integer value.
Convert first to the most precision number you could ever have e.g. decimal(9,2) then convert to an int. You can't convert directly from a decimal string to an int.
SELECT [Value]
, CONVERT(int,CONVERT(decimal(9,2),[Value]))
FROM (
VALUES ('15229.11'),('11092')
) x ([Value]);

Error converting data type varchar to float isnumeric = 1

When I run the script:
select
cast(s as float)
from
t
where
ISNUMERIC(s) = 1
it stops with the error:
Error converting data type varchar to float.
Why does it happen? I'm trying to convert to float only numerics. How do I found out which row causes the error?
The isnumeric function thinks just about everything is a number. Use "try_convert" instead. if the value can't convert to your destination datatype, it returns null.
select convert(float, '1,0,1')
where try_convert(float, '1,0,1') is not null
If you are on an older version of SQL, I would write my own function.
I usually face with this when the value in a column you are trying to convert to float contains a comma (,) as thousand separator:
SELECT ISNUMERIC('140,523.86')
The Result is 1, but unable to cast it as a float.
By replacing it works fine for me:
SELECT
CAST( replace(s,',','') AS float ) AS Result
FROM t
WHERE ISNUMERIC(replace(s,',','')) = 1
ISNUMERIC() function will return 1 for values like 123e3 because these values are Interpreted as numeric values. Because sql server sees this as 123 , 3 to the powers of 10 which is really a numeric value.
You should try something like....
Select *
From tableName
WHERE Col NOT LIKE '%[^0-9]%'
This will return any row where there is a non-numeric character, even values with a ..

How to SUBSTR a calculated row in SQL Query?

Original Query:
SELECT F4105.COUNCS/10000 FROM F4105
Output:
Numeric Expression
--------------------
111.1643000000000000
111.1633000000000000
111.1633000000000000
101.7654000000000000
101.7654000000000000
112.7258000000000000
I need to remove at least the last 5 zeroes. I tried to do a substring but it didn't work.
Here is the query(s) i tried:
(1)
SELECT SUBSTR((F4105.COUNCS/10000 AS 'co'),length((co)-5) FROM F4105
(2)
SELECT SUBSTR((F4105.COUNCS/10000),length((F4105.COUNCS/10000)-5)) FROM F4105
The 1st query gave me and error:
Token F4105 was not valid. Valid tokens: (.
The 2nd query worked by wrong output.
SUBSTR
00
000000
000000
000000
000000
000000
You are mixing the column alias definition in the expression. So, the correct expression is more like:
SELECT SUBSTR(F4105.COUNCS/10000, length(F4105.COUNCS/10000.0) - 5) as coFROM F4105
I wouldn't recommend doing this, however. You have a numeric expression. Just convert it to a decimal representation that you want, say:
SELECT CAST(F4105.COUNCS/10000.0 as DECIMAL(10, 5))
The syntax for SUBSTR scalar is effectively SUBSTR(expression, start-pos, for-length) IBM i 7.1->Database->Reference->SQL reference->Built-in functions->Scalar functions->SUBSTR
The LENGTH() expression shown used in the OP is specified for the second argument; i.e. the start-pos argument. As a starting position, the result of that string-length minus five calculation is conspicuously incorrect for obtaining the leftmost data; i.e. the starting-position is five bytes less than the length of the string. That would locate, of course, some insignificant zeroes five bytes from the end of the string-representation of the decimal-result of the division.
As effective correction therefore, would be either of • insert the constant integer value of 1 for the start-pos argument [thus making the LENGTH() expression become the third argument] • replace the SUBSTR scalar with the LEFT scalar.Either of those revisions would achieve something that at least resembles what is alluded as the desired output. However without either of the DDL and what should be the explicit output being expressed in the OP, the actual effect of those revised expressions could only be guessed.Anyhow, even with either of those changes, those suggested alternative character-string expressions remain as similarly poor [approaching daft] choice of expressions as the one in the OP, per lack of explicit casting; i.e. the two revised expressions suggested as possibly corrective [yet that remain similarly unlikely to yield desirable results] are:
SUBSTR((F4105.COUNCS/10000), 1,length((F4105.COUNCS/10000)-5))
LEFT((F4105.COUNCS/10000),length((F4105.COUNCS/10000)-5))
Having established data-type\length attributes using explicit casting [i.e. established even without some actual DDL to do so] in a derived-table expression that generates the input values that would produce the output shown in the OP, from a list of literal numeric values, the character-string expression in the following query ensures that only the eleven digits of decimal-precision to the right of the decimal point [i.e. the scale] are maintained; thus visually, the effect is that the trailing five digits are truncated:
with F4105 (COUNCS) as ( values
( dec( 1111643. , 9, 2 ) )
,( dec( 1111633. , 9, 2 ) )
,( dec( 1111633. , 9, 2 ) )
,( dec( 1017654. , 9, 2 ) )
,( dec( 1017654. , 9, 2 ) )
,( dec( 1127258. , 9, 2 ) )
)
SELECT cast( dec( (F4105.COUNCS/10000), 17, 11 ) as varchar(19) )
FROM F4105

Converting data types in SQL Server

I need to change some data types. I have tried using the CAST keyword, but it is not fixing the issue. Any suggestions on how to re-write these two lines with CAST statements?
Data loss might occur when casting from VarChar(100) to VarChar(20).
Code:
SELECT TOP 1 #variableId = variableId
FROM #tempTable
Data loss might occur when casting from NVarChar(512) to NVarChar.
Code:
SELECT myVariable
FROM tableName
I tried doing something like the following, but still produces an error:
CAST((myVariable) as nvarchar)
CAST is used for converting between data types. It sounds more like you should use LEFT instead:
SELECT TOP 1 #variableId = LEFT(variableId,20)
FROM #tempTable
This won't give you any warning as the system assumes you already know you're going to lose the right 80 characters.
For using CONVERT instead of CAST:
CONVERT(nvarchar, myVariable)
Is a valid syntax and also:
CONVERT(varchar(20), myVariable)
But for getting a part of a string we use SUBSTRING() or LEFT() or RIGHT() functions like this:
SUBSTRING( value_expression , start_expression , length_expression )
Returns part of a character, binary, text, or image expression.
LEFT ( character_expression , integer_expression )
Returns the left part of a character string with the specified number of characters.
RIGHT ( character_expression , integer_expression )
Returns the right part of a character string with the specified number of characters.

SQL Character extraction

I would like to extract everything on the right side of the "underscore". I want to get 0000. I tried
select right('M_0000',charindex('_','M_0000')-1)
but end up with just 0. Why?
Since you are using CHARINDEX, i assume you are using SQL-SERVER.
So in your second field you should say how many characters you want. You can achieve that by doing LEN('M_0000') - charindex('_') :
select right('M_0000',len('M_0000') - charindex('_','M_0000'))
sqlfiddle demo
You were ending up with just one 0 because charindex('_') is 1, and you are telling the RIGHT function that you want 1 char from the right.
From the docs:
RIGHT ( character_expression , integer_expression )
character_expression Is an expression of character or binary data.
character_expression can be a constant, variable, or column.
character_expression can be of any data type, except text or ntext,
that can be implicitly converted to varchar or nvarchar. Otherwise,
use the CAST function to explicitly convert character_expression.
integer_expression Is a positive integer that specifies how many
characters of character_expression will be returned. If
integer_expression is negative, an error is returned. If
integer_expression is type bigint and contains a large value,
character_expression must be of a large data type such as
varchar(max).
You can use SUBSTRING instead of RIGHT:
select SUBSTRING('M_0000',charindex('_','M_0000')+1, LEN('M_0000')) // start at character n + 1