Error in if not exists query in SQL Server - sql-server

What is wrong with this following query? I can't find the error. Can anyone help
me with this issue?
IF (NOT EXISTS(SELECT *
FROM chennai_metro_data
WHERE TIME1 ='09:00' AND DATE1 ='1-23-2017'))
BEGIN
INSERT INTO chennai_metro_data
VALUES (2021700002,'1-23-2017','09:00',1,0,555555)
END
ELSE
BEGIN
UPDATE chennai_metro_data
SET CUMFLOW = 555555
WHERE TIME1 = '09:00' AND DATE1 = '1-23-2017'
END
I'm getting this error:
Msg 206, Level 16, State 2, Line 1
Operand type clash: int is incompatible with date

As a best practice, you should always define the list of columns you're inserting into when using INSERT - that helps avoid a lot of problems !
And also: for the dates, to be independent of any language & regional settings, try to use the ISO-8601 format - YYYYMDDD for just dates (no time), or YYYY-MM-DDTHH:MM:SS for date & time.
So try this code:
INSERT INTO chennai_metro_data(col1, col2, ...., colN)
VALUES (2021700002, '20170123', '09:00', 1, 0, 555555)
and replace col1 thorugh colN with your actual column names from that table that you want to insert data into.

Related

SQL: How to refer to a dynamic column name to make calculation

I'd like to update fields while referring to a dynamic column.
The goal is to automate a process because each month the column to refer to changes.
For example it's like having different columns like month1, month2, month3 until month24. Each month, only 1 column needs to be updated but it's a running number that is calculated in another table.
So my question is how to make the query dynamic so that every month i only update the column number that i want and not the other one.
I tried the script below but the following issue comes up
Error converting data type varchar to float.
DECLARE #PromoMonthNumber VARCHAR(60)
DECLARE #PromoMonth VARCHAR(600)
SET #PromoMonthNumber = (SELECT CurrentDemandIndex FROM RidgeSys) --This refer to a number that change all the time
SET #PromoMonth = 'SELECT ABC.PromotionHistory' + #PromoMonthNumber
UPDATE ABC
SET #PromoMonth = table2.promotionhistory
FROM ABC
INNER JOIN (
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
FROM Article
INNER JOIN ABC ON DEF.articlecode = ABC.Articlecode
) as table2
ON ABC.articlecode = table2.code)
Here is your issue:
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
Since #PromoMonth is defined as VARCHAR, if the value is non-numeric, it will fail. Here is an example:
This works fine:
declare #x varchar(100) = '1';
select sum(round(#x,0));
Result:
1
This fails with same error above:
declare #x varchar(100) = 'x';
select sum(round(#x,0));
Result:
Msg 8114, Level 16, State 5, Line 3
Error converting data type varchar to float.
You need to check that the value is numeric before you do the calculation.

System.Data.SqlClient.SqlException: String or binary data would be truncated

I am creating a web app in which I am executing a select command on my stored procedure, but I want to insert the same fetched data into another table.
So I tried to do something like the following
CREATE PROCEDURE profinalinstexpensesonid
(#from varchar(5000),
#to varchar(5000),
#trainer varchar(5000),
#sonvinid varchar(5000)
)
AS
BEGIN
INSERT INTO invoice(sonvinid, tid, date, brandname, zone, location, area, venuename, venue, instructore, amount)
SELECT
instructoreexpense.sonvinid,
sonvininsert.trainer,
CONVERT(VARCHAR, sonvininsert.date, 105) AS date,
sonvininsert.brandname,
SUBSTRING(sonvininsert.zone, 1, 1) AS zone,
sonvininsert.location,
sonvininsert.area,
companysonvinunitvenue.venuename,
sonvininsert.venue,
sonvininsert.instructore,
instructoreexpense.amount
FROM
instructoreexpense
LEFT OUTER JOIN
sonvininsert ON sonvininsert.sonvinid = instructoreexpense.sonvinid
AND sonvininsert.status = '0'
LEFT OUTER JOIN
finalinstructoreexpense ON finalinstructoreexpense.sonvinid = instructoreexpense.sonvinid
LEFT OUTER JOIN
companysonvinunitvenue ON companysonvinunitvenue.id = sonvininsert.comsonvinid
WHERE
sonvininsert.date BETWEEN CONVERT(DATETIME, #from, 105)
AND CONVERT(DATETIME, #to, 105)
AND sonvininsert.trainer = (SELECT empname
FROM trainerdetails
WHERE trid = #trainer)
AND instructoreexpense.sonvinid NOT IN (SELECT CAST(Item AS INTEGER)
FROM SplitString(#sonvinid, ','))
ORDER BY
instructoreexpense.sonvinid
END
and when I execute the stored procedure like
exec profinalinstexpensesonid '01-01-2013','01-01-2017','andrews'
I am getting the following error
Msg 8152, Level 16, State 13, Procedure profinalinstexpensesonid, Line 10
String or binary data would be truncated.
On my line 10 I have the following code
insert into invoice(sonvinid, tid, date, brandname, zone, location, area, venuename, venue, instructore, amount)
I don't know what is wrong here?
The error message states the size of a column in invoice table is less compared to the size of the data being inserted into it.
For example if column brandname has data type varchar(50) and you are trying to insert more than 50 characters then it will cause error.
To resolve this compare the size of columns in invoice with the size of the columns being inserted.
You need to check column size of invoice table as well as columns in select list from which you are populating data.
Let's say you are inserting column "B" having data type as varchar(70) from table2 in column "A" having data type varchar(50) in table1; this won't work as you are trying to insert 70 characters in 50 varchar sized column.
Check source & destination column data type & it's length; and change it and try again.

Bad Dates: SQL Server Offers ISDATE(), But Informix Does Not. Is There an Equal Workaround?

I am dealing with legacy Informix data apparently never validated properly upon input.
This means that a DATE field could contain
a proper date (12/25/2000),
a garbage date (02/22/0200),
NULL, or
the Lindbergh baby.
The following works nicely in SQL Server:
SELECT
COUNT(1) AS [Grand Total Count of Bad-Date Records],
COUNT(GOOFYDATE) AS [Count of Just NON-NULL Bad-Date Records],
SUM(IIF(GOOFYDATE IS NULL,1,0)) AS [Count of Just NULL Bad-Date Records]
FROM MyTable
WHERE ISDATE(GOOFYDATE)=0
Everything above adds up.
In Informix,
SELECT COUNT(1)
FROM MyTable
WHERE DATE(GOOFYDATE) IS NULL
gives me the Grand Total, as before. However, the following does, too:
SELECT COUNT(1)
FROM MyTable
WHERE DATE(GOOFYDATE) IS NULL
AND GOOFYDATE IS NULL
How may I implement in Informix my ISDATE goal, as accomplished above in SQL Server?
You can write a stored procedure/function to perform this task, so that it will work exactly like the SQL Server equivalent. Something like:
CREATE FUNCTION informix.isdate(str VARCHAR(50), fmt VARCHAR(50))
RETURNING SMALLINT;
DEFINE d DATE;
ON EXCEPTION IN (-1277,-1267,-1263) -- other errors are possible
RETURN 0;
END EXCEPTION;
LET d = TO_DATE(str, fmt); -- acceptable date if exception not raised
IF d < MDY(1,1,1850) THEN -- dates prior to this are "logically invalid"
RETURN 0;
END IF;
RETURN 1;
END FUNCTION;
Which you can use thus:
-- Sample data
CREATE TEMP TABLE test1 (str VARCHAR(50));
INSERT INTO test1 VALUES ("not a date");
INSERT INTO test1 VALUES ("02/25/2016");
INSERT INTO test1 VALUES ("02/30/2016");
INSERT INTO test1 VALUES ("02/01/0000");
SELECT str, ISDATE(str, "%m/%d/%Y") FROM test1;
str (expression)
not a date 0
02/25/2016 1
02/30/2016 0
02/01/0000 0
4 row(s) retrieved.
SELECT str AS invalid_date
FROM test1
WHERE ISDATE(str, "%m/%d/%Y") = 0;
invalid_date
not a date
02/30/2016
02/01/0000
3 row(s) retrieved.
Depending on how goofy your dates are, you may find other errors crop up. Just adjust the ON EXCEPTION clause accordingly. I've written this function to be as general purpose as possible, but you could code the "accepted" date format into the routine rather than pass it as an argument. (I don't recommend that, though.)

Error converting data type varchar to numeric. SQL Server

I'm writing data on the Sql Server database.
When data is written, a trigger runs.
TRIGGER
ALTER TRIGGER Alert ON records AFTER INSERT AS
BEGIN
DECLARE #tempmin decimal = 0
DECLARE #current_max_idAlarm int = (SELECT MAX(IdAlarm) FROM alarms)
DECLARE #maxidAlarm int
DECLARE #temp decimal = (SELECT s.lim_inf_temp from sensores s JOIN inserted i ON s.idSensor=i.idSensor )
-- Insert into alares from the inserted rows if temperature less than tempmin
SET IDENTITY_INSERT alarmes On
INSERT alarmes (IdAlarm, desc_alarm,date, idRecord)
SELECT
ROW_NUMBER() OVER (ORDER BY i.idRecord) + #current_max_idAlarm, 'Temp Error', GETDATE(), i.idRecord
FROM
inserted AS i
WHERE
i.Temperature < #temp
end
INSERT
insert into record values ('2014-05-26' ,'14:51:47','Sensor01','---','48.6','9.8');
Whenever I try to record this type of data: '---'
Gives the following error:
Msg 8114, Level 16, State 5, Procedure Alert, Line
Error converting data type varchar to numeric.
I know it is to be in decimal type (DECLARE #temp decimal - TRIGGER), but moving to the type varchar to trigger stops working correctly.
Does someone can help me resolve this error please?
Thank you all.
You are trying to insert --- inside a numeric column, you simply can't do that.
You have mainly 2 options:
Change the data type of the destination column
Choose a different value to insert (like NULL)

Validate Date Values in NVarchar field

Hi I have a reporting application written against some 3rd party software. Unfortunately it stores all values as nvarchar and does not validate data entry on the client side as a result I am getting the following error when
"Conversion failed when converting date and/or time from character string"
System.Data.SqlClient.SqlException was unhandled by user code
or if I try to execute the code in SSMS:
Msg 241, Level 16, State 1, Procedure settlement_list, Line 10
Conversion failed when converting date and/or time from character string.
I assume this is the result of someone entering a text value in the data field so I've tried this ISDATE code to find the bad value:
SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02 FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) <> 1
AND Coalesce(mat3_04_02, '') <> ''
order by mat3_04_02 desc
and I get zero row returned ... I also manually sifted through the data (its sveral 100 thousand rows so its kind of hard and see no bad values ???
Does anyone have any suggestions ?
EDIT ---
Here is the stored proc (I know where clause is ugly)
SELECT mat_no, 'index'=matter.mat1_01_06,
'insurance'=Replace(Replace(matter.mat1_03_01, 'INSURANCE COMPANY', ' '), 'COMPANY', ''),
matter.[status], 'casestage'=mat1_04_01, 'injured'=matter.MAT1_01_07, matter.client,
'terms'=mat3_04_06, 'ClmAmt'=matter.mat1_07_01,
'ClmBal'=matter.mat1_07_03, 'SetTot'=matter3.MAT3_04_09, 'By'=mat3_03_02,
'DtSttld'=mat3_04_02, 'SettlStg'=(MAT3_06_08 + ' / ' + MAT3_06_05)
FROM [lntmu11].matter3 inner join
[lntmu11].matter ON [lntmu11].matter.sysid = [lntmu11].matter3.sysid
WHERE
(DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = #range
and mat3_03_02 like #by)
or
(mat3_04_06 like #by2
and DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = #range)
ORDER BY MAT3_03_02
You can't force the order the query engine will try to process the statement without first dumping the ISDATE() = 1 rows into a #temp table. You can't guarantee the processing order or short circuiting, even though some will suggest using a CTE or subquery to filter out the bad rows first. So some might suggest:
;WITH x AS
(
SELECT mat3_02_01, mat3_04_02
FROM Intmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
AND mat3_04_02 IS NOT NULL -- edited!
)
SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02
FROM x
ORDER BY mat3_04_02 DESC;
And this may even appear to work, today. But in the long term, really the only way to guarantee this processing order - in current versions of SQL Server - is:
SELECT mat3_02_01, mat3_04_02
INTO #x
FROM Intmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
AND mat3_04_02 IS NOT NULL; -- edited!
SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02
FROM #x
ORDER BY mat3_04_02 DESC;
Have you thought about validating the values on input? For example, you can change where this error appears in the application by slapping them on the wrist when they enter an invalid date, instead of punishing the person who selects their bad data. If you are controlling the update/insert via a stored procedure, you can say:
IF ISDATE(#mat3_04_02) = 0
BEGIN
RAISERROR('Please enter a valid date.', 11, 1);
RETURN;
END
If you aren't controlling data manipulation via stored procedure(s), then you can add a check constraint to the table (after you've cleaned up the existing bad data).
UPDATE Intmu11.matter3 SET mat3_04_02 = NULL
WHERE ISDATE(mat3_04_02) = 0;
ALTER TABLE Intmu11 WITH NOCHECK
ADD CONSTRAINT mat3_04_02_valid_date CHECK (ISDATE(mat3_04_02)=1);
This way when the error message gets bubbled up to the user they will see the constraint name and hopefully will be able to map that to the data entry point on the front end that failed:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted
with the CHECK constraint "mat3_04_02_valid_date". The conflict
occurred in database "your_db", table "Intmu11.matter3", column
'mat3_04_02'. The statement has been terminated.
Or better yet, use the right data type in the first place! Again, after updating the existing bad data to be NULL, you can say:
ALTER TABLE Intmu11.matter3 ALTER COLUMN mat3_04_02 DATETIME;
Now when someone tries to enter a non-date, they'll get the same error that the users are currently getting when they try to select the bad data:
Msg 241, Level 16, State 1, Line 1 Conversion failed when
converting date and/or time from character string.
In SQL Server 2012, you'll be able to get around this with TRY_CONVERT() but you should still be trying to get the data type right from the beginning.
Examine the query where
ISDATE(mat3_04_02) = 1
AND
Coalesce(mat3_04_02, '') = ''
To be a date it must have a value.
But is only matches the second condition if it has not value.
The intersection (and) of those two conditions is always false.
If you are looking for null then "mat3_04_02 is null" but it still will return 0 rows.
Try
SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02
FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
order by CONVERT(datetime, mat3_04_02) desc
I think you would want date sorted and not string sorted
The question started as finding valid dates and it morphed into finding invalid dates
SELECT mat3_02_01, mat3_04_02
FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) = 0
AND mat3_04_02 is not null
order by mat3_04_02) desc

Resources