SQL Server 2005 I am not able to read from a table - sql-server-2005

Please suppose that in SQL Server 2005, if you launch the following query:
SELECT CHICKEN_CODE FROM ALL_CHICKENS WHERE MY_PARAMETER = 'N123123123';
you obtain:
31
as result.
Now, I would like to write a function that, given a value for MY_PARAMETER, yields the corresponding value of CHICKEN_CODE, found in the table ALL_CHICKENS.
I have written the following stored function in SQL Server 2005:
ALTER FUNCTION [dbo].[determines_chicken_code]
(
#input_parameter VARCHAR
)
RETURNS varchar
AS
BEGIN
DECLARE #myresult varchar
SELECT #myresult = CHICKEN_CODE
FROM dbo.ALL_CHICKENS
WHERE MY_PARAMETER = #input_parameter
RETURN #myresult
END
But if I launch the following query:
SELECT DBO.determines_chicken_code('N123123123')
it yields:
NULL
Why?
Thank you in advance for your kind cooperation.

define the length of your varchar variables like this
varchar(100)
Without the 100 (or whatever length you choose) its lengh is 1 and the where clause will filter out the correct results.

Specify a length for your varchar (ex.: varchar(100)). Without length, varchar = 1 char.

As per other PS, You can store only one char in the #myresult because you have not specified any length, bcoz 1 char length is default for Varchar datatype.
Why we are getting NUll, not the first char:
If there are multiple records are filtered on basis of Where clause in ALL_CHICKENS table then the value of CHICKEN_CODE column is picked up from last row in ALL_CHICKENS table.
It seems that the last row has null value in CHICKEN_CODE column.

Specify a length for #input_parameter, #myresult as by default varchar lengh is 1.

Related

Transact-SQL Select statement results with bad GUID

We have a table with GUID primary keys. When I search for a specific key, I can use either:
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE6'
SELECT * FROM products WHERE productID LIKE '34594289-16B9-4EEF-9A1E-B35066531DE6'
RESULT (for both):
product_ID Prd_Model
------------------------------------ --------------------------------------------------
34594289-16B9-4EEF-9A1E-B35066531DE6 LW-100
(1 row affected)
We have a customer who uses our ID but adds more text to it to create some kind of compound field in their own system. They sent me one of these values to look up and I had an unexpected result. I meant to trim the suffix but forgot, so I ran this:
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
When I ran it, I unexpectedly got the same result:
product_ID Prd_Model
------------------------------------ --------------------------------------------------
34594289-16B9-4EEF-9A1E-B35066531DE6 LW-062
(1 row affected)
Now if I trim a value off the end of the GUID when searching I get nothing (GUID is 1 digit short):
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE'
Result:
product_ID Prd_Model
------------------------------------ --------------------------------------------------
(0 rows affected)
When using the LIKE command instead of '=' and if I add the suffix to the end, the statement returns zero results. This is what I would expect.
So why does the longer string with the suffix added to the end return a result when using '=' in the statement? It's obviously ignoring anything beyond the 36-character GUID length but I'm not sure why.
This behaviour is documented:
Converting uniqueidentifier Data
The uniqueidentifier type is considered a character type for the purposes of conversion from a character expression, and therefore is subject to the truncation rules for converting to a character type. That is, when character expressions are converted to a character data type of a different size, values that are too long for the new data type are truncated. See the Examples section.
So, the string value '34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD' is truncated to '34594289-16B9-4EEF-9A1E-B35066531DE6' when it is implicitly cast (due to Data Type Precedence) to a uniqueidentifier and, unsurprisingly, '34594289-16B9-4EEF-9A1E-B35066531DE6' equals itself so the row is returned.
And the documentation does indeed give an example:
The following example demonstrates the truncation of data when the value is too long for the data type being converted to. Because the uniqueidentifier type is limited to 36 characters, the characters that exceed that length are truncated.
DECLARE #ID NVARCHAR(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong';
SELECT #ID, CONVERT(uniqueidentifier, #ID) AS TruncatedValue;
Here is the result set.
String TruncatedValue
-------------------------------------------- ------------------------------------
0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong 0E984725-C51C-4BF4-9960-E1C80E27ABA0
I, however, find it odd that you say that the statement below returns no rows:
SELECT *
FROM products
WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE'
Though true, it won't return rows, it will also error:
Conversion failed when converting from a character string to uniqueidentifier.
The fact it doesn't implies your column isn't a uniqueidentifier which would mean that your first statement isn't true; as the longer string would not be truncated. This means that one of the statements in the question is likely wrong; either your column is a uniqueidentifier and thus you get results but get an error in the latter, or it isn't and neither statement would return a result set. As you can see in this demonstration:
CREATE TABLE dbo.YourTable (UID uniqueidentifier, String varchar(36));
INSERT INTO dbo.YourTable (UID,String)
VALUES('34594289-16B9-4EEF-9A1E-B35066531DE6','34594289-16B9-4EEF-9A1E-B35066531DE6');
GO
--Returns data
SELECT *
FROM dbo.YourTable
WHERE UID = '34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
GO
--Errors
SELECT *
FROM dbo.YourTable
WHERE UID = '34594289-16B9-4EEF-9A1E-B35066531DE';
GO
--Returns no data
SELECT *
FROM dbo.YourTable
WHERE String = '34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
GO
--Returns no data
SELECT *
FROM dbo.YourTable
WHERE String = '34594289-16B9-4EEF-9A1E-B35066531DE'
GO
DROP TABLE dbo.YourTable;
db<>fiddle

Nvarchar working with logical operator working?

Just need your help here.
I have a table T
A (nvarchar) B()
--------------------------
'abcd'
'xyzxcz'
B should output length of entries in A for which I did
UPDATE T
SET B = LEN(A) -- I know LEN function returns int
But when I checked out the datatype of B using sp_help T, it showed column B as nvarchar.
What's going on ?
select A
from T
where B > 100
also returned correct output?
Why is nvarchar working with logical operators ?
Please help.
Check https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-2017 where it is said that data types are converted explicitly or implicitly when you move, compare or store a variable. In your case, you are comparing column B with 100, forcing sql server to implicitly convert it to integer type (check the picture about conversions on the same page). As a prove, try to alter a row putting some text in column B and, after repeating your select query B>100, sql server will throw a conversione error trying to obtain an integer out of your text.
It works because of implicit conversion between types.
Data type precedence
When an operator combines expressions of different data types, the data type with the lower precedence is first converted to the data type with the higher precedence. If the conversion isn't a supported implicit conversion, an error is returned.
Types precedence:
16. int
...
25. nvarchar (including nvarchar(max) )
In you example:
select A
from T
where B > 100
--nvarchar and int (B is implicitly casted to INT)
when adding a column to a table in ssms, not adding a datatype a "default" datatype is chosen. for me on 2017 developer it's nchar(10). if you want it to be int define the column with datatype of int. in tsql it'd be
create table T (
A nvarchar --for me the nvarchar without a size gives an nvarchar(2)
,B int
);
sp_help T
--to make a specific size, largest for nvarchar is 4000 or max...max is the replacement for ntext of old, as.
create table Tmax (
A nvarchar(max)
,B int
);
--understanding nvarchar and varchar for len() and datalength()
select
datalength(N'wibble') datalength_nvarchar -- nvarchar is unicode and uses 2 bytes per char, so 12
,datalength('wibble') datalength_varchar -- varchar uses 1 byte per so 6
,len(N'wibble') len_nvarchar -- count of chars, so 6
,len('wibble') len_varchar -- count of char so still 6
nvarchar(max) and varchar(max)
hope this helps, the question is a bit discombobulated

using parameters with max len and check for null vall

I'm trying to get a count for a column to see the max characters. I'm getting a warning, I know it doesn't effect, but it's more of an annoyance and would like to eliminate the warning.
My example is as follows:
Declare #Countthis varchar (255)
select #Counthis = max(len(col1)) from #temp
Print '------- This is the largest count for this column-----' + #Countthis
The warning I receive is:
Warning: Null value is eliminated by an aggregate or other SET operation.
I tried using Case statement but I couldn't figure it out. If the value is NULL just ignore the value.
Is this possible?
You can use
Declare #Countthis varchar (255)
select #Counthis = max(len(IsNull(col1,''))) from #temp

SQL Server Management Studio ZEROFILL

I am trying to add a auto_increment primary key with ZEROFILL with a max size of six.
So it outputs:
000001
000002 etc...
However I am really struggling to achieve this and cant find the answer. How do I set up this column type in SQL Server Management Studio?
Thanks
You cannot do this with an integer field in SQL Server (nor would I recommend it with a Varchar).
Let SQL Server store the field as an Identity, and then (assuming this is for display), format the data when you select it like such:
SELECT RIGHT('000000' + CONVERT(VARCHAR(6),ID), 6) FROM Table
What you're trying to achieve is not possible. Display formatting is done in a presentation layer and not in the database. You need to separate a value from the presentation of a value. The two values 1 and 000001 are the same.
If you want to return something formatted, then you would have to return the value as a string. Just cast it to a string, add a number of zeroes at beginning and then keep the leftmost n characters.
SELECT FORMAT(2, N'000000')
--OR
SELECT FORMAT(2, CAST(REPLICATE(0, 6) AS NVARCHAR(6)))
https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql?view=sql-server-ver15
By creating a function
CREATE FUNCTION MyZeroFill (
#N BIGINT,
#D SMALLINT
) RETURNS VARCHAR(50) AS
BEGIN
RETURN RIGHT('0000000000000000000000000000000000000000000000'+CAST
(#N AS VARCHAR),#D)
END

String or binary data would be truncated. The statement has been terminated

I have met some problem with the SQL server, this is the function I created:
ALTER FUNCTION [dbo].[testing1](#price int)
RETURNS #trackingItems1 TABLE (
item nvarchar NULL,
warehouse nvarchar NULL,
price int NULL
)
AS
BEGIN
INSERT INTO #trackingItems1(item, warehouse, price)
SELECT ta.item, ta.warehouse, ta.price
FROM stock ta
WHERE ta.price >= #price;
RETURN;
END;
When I write a query to use that function like the following it getting the error
String or binary data would be truncated. The statement has been terminated
How can I fix this problem?
select * from testing1(2)
This is the way I create the table
CREATE TABLE stock(item nvarchar(50) NULL,
warehouse nvarchar(50) NULL,
price int NULL);
When you define varchar etc without a length, the default is 1.
When n is not specified in a data definition or variable declaration statement, the default length is 1. When n is not specified with the CAST function, the default length is 30.
So, if you expect 400 bytes in the #trackingItems1 column from stock, use nvarchar(400).
Otherwise, you are trying to fit >1 character into nvarchar(1) = fail
As a comment, this is bad use of table value function too because it is "multi statement". It can be written like this and it will run better
ALTER FUNCTION [dbo].[testing1](#price int)
RETURNS
AS
SELECT ta.item, ta.warehouse, ta.price
FROM stock ta
WHERE ta.price >= #price;
Of course, you could just use a normal SELECT statement..
The maximal length of the target column is shorter than the value you try to insert.
Rightclick the table in SQL manager and go to 'Design' to visualize your table structure and column definitions.
Edit:
Try to set a length on your nvarchar inserts thats the same or shorter than whats defined in your table.
In my case, I was getting this error because my table had
varchar(50)
but I was injecting 67 character long string, which resulted in thi error. Changing it to
varchar(255)
fixed the problem.
Specify a size for the item and warehouse like in the [dbo].[testing1] FUNCTION
#trackingItems1 TABLE (
item nvarchar(25) NULL, -- 25 OR equal size of your item column
warehouse nvarchar(25) NULL, -- same as above
price int NULL
)
Since in MSSQL only saying only nvarchar is equal to nvarchar(1) hence the values of the column from the stock table are truncated
SQL Server 2016 SP2 CU6 and SQL Server 2017 CU12
introduced trace flag 460 in order to return the details of truncation warnings.
You can enable it at the query level or at the server level.
Query level
INSERT INTO dbo.TEST (ColumnTest)
VALUES (‘Test truncation warnings’)
OPTION (QUERYTRACEON 460);
GO
Server Level
DBCC TRACEON(460, -1);
GO
From SQL Server 2019 you can enable it at database level:
ALTER DATABASE SCOPED CONFIGURATION
SET VERBOSE_TRUNCATION_WARNINGS = ON;
The old output message is:
Msg 8152, Level 16, State 30, Line 13
String or binary data would be truncated.
The statement has been terminated.
The new output message is:
Msg 2628, Level 16, State 1, Line 30
String or binary data would be truncated in table 'DbTest.dbo.TEST', column 'ColumnTest'. Truncated value: ‘Test truncation warnings‘'.
In a future SQL Server 2019 release, message 2628 will replace message 8152 by default.