SQL varchar to bit error - sql

Okay, I'm getting this error when I try to execute this procedure. The thing is I'm not trying to convert to a bit at any time. At least not on purpose. I'm a bit stumped at the moment.
Declare #AValue varchar(max)
set #AValue = (SELECT Value
FROM dbo.Tbl
WHERE Name=#FILE
AND Value LIKE (CAST(#MODID as varchar(15))+'|%'))
set #AValue = PARSENAME(REPLACE(#AValue, '|', '.'), 1) -- Hack way to parse.
INSERT INTO dbo.Tbl
(
Name,
Value,
Type,
CDT,
UDT,
Active,
User
)
VALUES
(
'Agreement',
(CAST(#MODID AS varchar(15)) + '|' + #AValue),
'Download',
GETDATE(),
GETDATE(),
1,
#USER
)

Check the triggers on the tables, particularly the insert. Lots of times unexplainable errors can lurk there.

Post the error, the CREATE PROCEDURE statement, and - most importantly - the call to the procedure that is failing. Also, what version of SQL Server are you using?
Most likely, the stored proc has a parameter of type BIT, and you are calling the procedure with a value like 'F', '-1' or some other string that can't be converted to BIT.

Sorry, found the answer. I came back today and the error I was getting was completely different than the one I had when I first asked the question. Sorry I forgot to write that error.
Problem was my WHERE clause was getting multiple returns from the database cause I had been testing a lot, so there were duplicate rows.

GetDate needs to be assigned to something in T-SQL before it can be used in a insert.
Try this:
DECLARE #CDT DateTime
DECLARE #UDT DateTime
SELECT #CDT = GetDate()
SELECT #UDT = GetDate()
INSERT INTO dbo.Tbl
(
[Name],
[Value],
[Type],
CDT,
UDT,
Active,
User
)
VALUES
(
'Agreement',
(CAST(#MODID AS varchar(15)) + '|' + #AValue),
'Download',
#CDT,
#UDT,
1,
#USER
)

Related

Must declare the scalar variable with SELECT statement

I have the following statement:
DECLARE #Nr_Karton int;
SELECT #Nr_Karton = ISNULL(MAX(Nr), 1000) FROM W_Karton;
SET #Nr_Karton = #Nr_Karton + 1;
INSERT INTO W_Karton (Container_ID, Nr, Beschrieb, CreationDate, Location)
VALUES ('1', #Nr_Karton, '', getDate(), 'Bösingen');
But I get the error:
[SQL] SELECT #Nr_Karton = ISNULL(MAX(Nr), 1000) FROM W_Karton
[Err] 42000 - [SQL Server]Must declare the scalar variable "#Nr_Karton".
How to get rid of the error?
I did some playing with this. The fictional schema I created was:
CREATE TABLE W_Karton (Container_ID int, Nr int, Beschrieb varchar(1),
CreationDate datetime, Location varchar(10))
Whilst it parsed and ran fine on my local 2008R2 box, the same code did not work when pasted into a SQL Fiddle.
However, if you remove all the semi-colons apart from the last one as per this SQL Fiddle you can see it seems to work fine!
I believe it shouldn't make any difference, but if you would rather it worked and don't care about the why, give it a try...
I encountered the same issue. It turns out it is due to ';' being selected as the "Query Terminator". IN SQL Fiddle, this actually means "batch terminator". There should be a drop-down button on the bottom right that has the text "[;]". Click that and select "Keyword [GO]".

TSQL function which will raiserror if passed null?

I'm looking to add some code to my TSQL arsenal to defend against performing aggregations in SQL when the data in a column is null. Ideally there would be a SUM_NN (for sum no null), in sql server which would raiserror if any of the values were null.
Since you can't raiserror from a UDF, the only way I could think of doing it looked like this, though I don't like this solution:
CREATE FUNCTION dbo.NULL_TEST_F(#arg FLOAT)
RETURNS FLOAT
AS
BEGIN
IF(#arg IS NULL)
SELECT 1/0
RETURN #arg
END
Note: I think this is stupid solution, but I've gotten burned way too many times when I'm missing data. Also, we're using SQL Server 2005, but I'm open to 2008 and 2012 solutions. Additionally, I'd like to know how other databases deal with this type of issue.
This was my final solution:
CREATE FUNCTION [dbo].[NullTest_F]
(
#input FLOAT,
#message VARCHAR(100)
)
RETURNS FLOAT
AS
BEGIN
DECLARE #test INT
IF(#input IS NULL)
SELECT #test = CAST(#message AS INT)
RETURN #input
END
I can then embed this with a useful error message when running aggregate functions. Example:
CREATE TABLE Data (
Date DATETIME,
DataPoint FLOAT
)
INSERT INTO Data (Date, DataPoint) VALUES ('2012-03-01', 4)
INSERT INTO Data (Date, DataPoint) VALUES ('2012-03-02', 6)
SELECT SUM(NullTest_F(DataPoint, 'Missing data at' + CONVERT(VARCHAR(10), Data))
FROM Data
Maybe this one will help:
https://stackoverflow.com/a/4681815/1371070
You could create a function like suggested in the answer linked above and call it from your aggregate in case #arg is null.
It's still the same strategy overall but It's a better error to throw than divide-by-zero, I guess.

Transact SQL, how can I take varchar type, convert to int, add one, convert back to string, then store?

ALTER PROCEDURE [dbo].[AmendInsertDuplicateFields] (#ReportID varchar(50))
AS
BEGIN
DECLARE #NewReportID VARCHAR(50)
SET #NewReportID = NEWID()
INSERT INTO [MVCOmar].[dbo].[PrideMVCCollisionBegin]
([ReportID], [LocalIncidentNum], [version], [MTOReferenceNo], [Submitted])
SELECT
#NewReportID, [LocalIncidentNum], [version], [MTOReferenceNo], [Submitted]
FROM
[MVCOmar].[dbo].[PrideMVCCollisionBegin]
WHERE
[ReportID] = #ReportID;
I would like to take the result that I get for version, convert it from string to int type, add one, convert back to string, and store it.
I acknowledge that version should be int and not string type. I also acknowledge that an even better method of accomplishing this would be to set properties to increment by one.
I can't do either of those option for the time being because my priorities are different right now, I am time limited, the code is very old, and written by numerous people which carried poor coding habits.
you don't need to convert it, run this, there will be an implicit conversion
SELECT '1' + 1
That returns 2
In your case you can just do [version] + 1
You can do this inline in your SELECT statement, using the CONVERT function:
INSERT INTO [MVCOmar].[dbo].[PrideMVCCollisionBegin] ([ReportID], [LocalIncidentNum], [version], [MTOReferenceNo], [Submitted])
SELECT #NewReportID, [LocalIncidentNum],
CONVERT(VARCHAR, (CONVERT(INT, [version]) + 1)),
[MTOReferenceNo], [Submitted]
FROM [MVCOmar].[dbo].[PrideMVCCollisionBegin]
WHERE [ReportID]=#ReportID;
SQL Server supports CAST or CONVERT
CAST(col1 as int)
CONVERT(int,col1)

Why does my sql date comparison return 0 results

I apologize in advance if this question is too long but I wanted to make sure I included all the steps I followed to get to this point.
I have the following table in my SQL Server 2008 database:
CREATE TABLE [VSPRRecalc](
[VSPRDate] [datetimeoffset](7) NOT NULL,
[CalcType] [int] NOT NULL,
CONSTRAINT [PK_VSPRRecalc] PRIMARY KEY CLUSTERED ([VSPRDate] ASC)
It has some rows in it that look like this:
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-15 10:17:49.5780000 -05:00','3')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-16 07:44:03.3750000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-17 07:40:40.1090000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-18 16:29:02.2203744 -05:00','2')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-20 09:58:50.1250000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-29 19:21:26.8120000 -05:00','1')
I'm using linq to check and see if a given date already exists in this table:
var recalc = (from re in VSPRRecalcs
where re.VSPRDate.Date == oDate.Value.Date
select re).SingleOrDefault();
Currently recalc returns null whenever the date is within 5 hours of midnight (like the 12-29 case in the insert statements above). I checked and the following sql is being executed:
exec sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
FROM [dbo].[VSPRRecalc] AS [t0]
WHERE
CONVERT(DATE, [t0].[VSPRDate]) = #p0',N'#p0 datetime',#p0='2010-12-29'
Which returns 0 records. I modified the query to make the test easier to play with and came up with the following:
declare #t as date
set #t = '2010-12-29'
select *,
case when CONVERT(DATE, [VSPRDate]) = #t then 'true' else 'false' end
from VSPRRecalc where
CONVERT(DATE, [VSPRDate]) = #t
That query works for any other date in the table but not for any date that is within 5 hours of midnight (again see 12-29 above). If I run the above query without the where clause the 12-29 row does have 'true' displayed so clearly the boolean is evaluating the way I expect in the select statement but not in the where clause. Why does that happen?
I would say that's a bug on SQL Server, regarding conversion between the DATETIMEOFFSET time and the more "standard" types DATETIME and DATE...
What I have find out is the following:
This works:
EXEC sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
FROM [dbo].[VSPRRecalc] AS [t0]
WHERE [t0].[VSPRDate] = #p0',
N'#p0 DATETIMEOFFSET(7)',
#p0 = '2010-12-29 19:21:26.8120000 -05:00'
Which means that when we keep using DATETIMEOFFSET, there is no problem whatsoever... Still, you seem to need to find all records in a given day, not search for an exact DATETIMEOFFSET, right?
So, probably a little bit more useful, this works also:
EXEC sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
FROM [dbo].[VSPRRecalc] AS [t0]
WHERE [t0].[VSPRDate] BETWEEN #p0 AND #p1',
N'#p0 DATETIMEOFFSET, #p1 DATETIMEOFFSET',
#p0 = '2010-12-29 00:00:00.0000000 -05:00',
#p1 = '2010-12-30 00:00:00.0000000 -05:00'
I guess the secret here is keep using the DATETIMEOFFSET data type (and it's CLR equivalent, System.DateTimeOffset). That way you will not get into this conversion issue...
(And, by the way, you should use a BETWEEN for searching records based on a date anyway. This allows the DBMS to use an index over that column, which is not possible when your WHERE clause is making a function call or a hard-coded conversion).
Edit I forgot there is no BETWEEN operator available for Linq for SQL - but that's easy to fix, just use something like WHERE [t0].[VSPRDate] >= #p0 AND [t0].[VSPRDate] <= #p1'... Also, this SO question is about declaring an extension method in order to implement it, but I don't know if it works...

String manipulation SQL

I have a row of strings that are in the following format:
'Order was assigned to lastname,firsname'
I need to cut this string down into just the last and first name but it is always a different name for each record.
The 'Order was assigned to' part is always the same.......
Thanks
I am using SQL Server. It is multiple records with different names in each record.
In your specific case you can use something like:
SELECT SUBSTRING(str, 23) FROM table
However, this is not very scalable, should the format of your strings ever change.
If you are using an Oracle database, you would want to use SUBSTR instead.
Edit:
For databases where the third parameter is not optional, you could use SUBSTRING(str, 23, LEN(str))
Somebody would have to test to see if this is better or worse than subtraction, as in Martin Smith's solution but gives you the same result in the end.
In addition to the SUBSTRING methods, you could also use a REPLACE function. I don't know which would have better performance over millions of rows, although I suspect that it would be the SUBSTRING - especially if you were working with CHAR instead of VARCHAR.
SELECT REPLACE(my_column, 'Order was assigned to ', '')
For SQL Server
WITH testData AS
(
SELECT 'Order was assigned to lastname,firsname' as Col1 UNION ALL
SELECT 'Order was assigned to Bloggs, Jo' as Col1
)
SELECT SUBSTRING(Col1,23,LEN(Col1)-22) AS Name
from testData
Returns
Name
---------------------------------------
lastname,firsname
Bloggs, Jo
on MS SQL Server:
declare #str varchar(100) = 'Order was assigned to lastname,firsname'
declare #strLen1 int = DATALENGTH('Order was assigned to ')
declare #strLen2 int = len(#str)
select #strlen1, #strLen2, substring(#str,#strLen1,#strLen2),
RIGHT(#str, #strlen2-#strlen1)
I would require that a colon or some other delimiter be between the message and the name.
Then you could just search for the index of that character and know that anything after it was the data you need...
Example with format changing over time:
CREATE TABLE #Temp (OrderInfo NVARCHAR(MAX))
INSERT INTO #Temp VALUES ('Order was assigned to :Smith,Mary')
INSERT INTO #Temp VALUES ('Order was assigned to :Holmes,Larry')
INSERT INTO #Temp VALUES ('New Format over time :LootAt,Me')
SELECT SUBSTRING(OrderInfo, CHARINDEX(':',OrderInfo)+1, LEN(OrderInfo))
FROM #Temp
DROP TABLE #Temp