Why do I get "Conversion failed when converting date and/or time from character string" when subtracting a number from GETDATE()? - sql-server

I cannot figure out what I am doing incorrect here. I have the following values for these variables.
my $sql = qq~
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('X','Y','Z')
AND CAST(u.InspectionStartDate AS DATETIME) > (GETDATE() - ?)
~;
my $argsRef->{lookBack} = 30;
And when I try to run a selectrow_array on the sql like such:
my $qnCount = $dbh->selectrow_array($sql, undef, $argsRef->{lookBack});
I get the following error:
DBD::ODBC::db selectrow_array failed: [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting date and/or time from character string. (SQL-22007) [for Statement "
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('X','Y','Z')
AND CAST(u.InspectionStartDate AS DATETIME) > (GETDATE() - ?)
"]
So, it is my understanding that the third parameter in the selectrow_array call from a database handle should be the bind variables. Yet, they seem not to be binding....
the database handle is created as such:
my $dbh = DBI->connect_cached("dbi:ODBC:$dsn", undef, undef, {
PrintError => 0,
RaiseError => 1,
ShowErrorStatement => 1,
LongReadLen => 500000,
})
$dsn is the correct DSN but not shown for various reasons, but we know it works due the error message coming back from SQL Server.
Any idea what I am doing wrong?
Thanks in advance for your help.

First, a shout out to ThisSuitIsBlackNot for pointing out that the problem. I made the assumption that the DBI/driver would be able to determine the value type. That was wrong. So, I explicitly stated the type:
$sth = $dbh->prepare($sql);
$sth->bind_param( 1, ($argsRef->{lookBack} * -1), { TYPE => SQL_INTEGER });
$sth->execute();
my $qnCount = $sth->fetchrow_array();
This allowed it to go through as an integer and the SQL ran without problem.
In case you were wondering why I am multiplying by -1, is because I changed the query to use DATEADD:
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('x')
AND CAST(u.InspectionStartDate AS DATETIME) > DATEADD(dd, ?, GETDATE())
Although there seems to be some continuing discussion in regards to its use, it is working here.
Thank you all for your help.

Related

Dynamic SQL query with cell reference in Excel

I have a query connected to a pivot table and I want it to show results based on a date from cell (so the user can change it without editing the query). I've read one way to do it is creating a connection to the cell
And drilling down that query so its data that can be referenced by another query
I've read I have to reference that connected table (just a date) through
SQL1 = Text.Combine({SQL,Date}),
SQL2 = Text.Combine({SQL1, "‘" }),
Source = Sql.Database("servername", "db", [Query= SQL2])
So I think it should look like this:
let
SQL =
"select trim(codart) AS REF,
descart AS 'DESCRIPTION',
codalm AS WAREHOUSE,
descalm AS WAREHOUSEDESCRIP,
unidades AS UNITS,
entran AS 'IN',
salen AS 'OUT',
m.entran*1 + m.salen*-1 as MOVEMENT,
(select sum(m1.entran*1 + m1.salen*-1)
from MOVSTOCKS m1
where m1.codart = m.codart and m1.codalm =
m.codalm and m.fecdoc >= m1.fecdoc) as 'CUMULATIVE',
PRCMEDIO as 'VALUE',
FECDOC as 'DATE',
REFERENCIA as 'REF',
tipdoc as 'DOCUMENT'
from (select m.*,
sum(m.entran*1 - m.salen*-1) over (partition by m.codart, m.codalm order by fecdoc) as cumulative,
max(fecdoc) over (partition by m.codart, m.codalm) as max_fecdoc
from MOVSTOCKS m
where fecdoc <= ‘ ), m
where fecdoc = max_fecdoc
and (m.entran <> 0 or m.salen <> 0)
order by fecdoc",
SQL1 = Text.Combine({SQL,Date}),
SQL2 = Text.Combine({SQL1, "‘" }),
Source = Sql.Database("servername", "db", [Query= SQL2])
in
Source
The problem is... if that dynamic cell is formated as date, the power query shows this error:
Expression.Error: We cannot convert the value #date (2020, 9, 30) to type Text.
Details:
Value= 30/09/2020
Type=Type
And if I format date as text, then it shows this error (after changing privacy options):
DataSource.Error: Microsoft SQL: Incorrect syntax near '‘'.
Details:
DataSourceKind=SQL
DataSourcePath=servername;db
Message=Incorrect syntax near '‘'.
Number=102
Class=15
I want SQL to read this
where fecdoc <= ‘ ), m
as
where fecdoc <= 30/09/2020 ), m
Having in mind that date comes from an excel cell that can be changed by the user.
I'm new with SQL and M, I don't even know if what I'm trying makes any sense.
Any feedback will be helpful. Thank you very much
Instead of whatever you're trying to do with SQL1 and SQL1, in your query, replace
where fecdoc <= ‘ ), m
with
where fecdoc <= '" & Date & "' ), m
where Date is a reference to your date in string format.

An invalid floating point operation occurred POWER SQL Server

I am have a problem with the code, when I run I get
An invalid floating point operation occurred
My code is the following:
select POWER( ISNULL(value1,0) / NULLIF(value2,0) , 12 / CONVERT(numeric(6,2),value3))
where value1(data type: money), value2(data type: money), value3(data type: int) are columns in my database.
I get that error when value1 = Null, value2 = 164083520.00 and value3 = 177
The weird is that if I replace with these numbers I get right result, but not while running this.
Any ideas?
Executing the following script I'm not getting any errors on SQL Server 2012. AFAICT you won't get any on other versions either. You must be having a calculation somewhere else that results in an invalid floating point operation.
DECLARE #values TABLE(value1 MONEY,value2 MONEY,value3 INT);
INSERT INTO #values(value1,value2,value3)VALUES(NULL,164083520.00,177);
SELECT
result=POWER(ISNULL(value1,0)/NULLIF(value2,0), 12.0/CONVERT(numeric(6,2),value3))
FROM
#values;
Result
0.00

SQL Server Cast varchar column value '1218300.00' as int

A large value in a column has caused my SQL to throw error msg:
Error converting data type varchar to numeric
I have isolated this to a particular row. Here is a simplified script that "works":
SELECT
MtgeLoanAmount
, CAST(convert(numeric(15,2),'1218300.00') as int) as TrialValue
FROM dbo.Processed_VA_From_Excel
where FipsStateCode='06'
and FipsCountyCode='013'
and GuarantyAmount = '304575'
which returns results as pasted here:
So when I try to "generalize" my test by adding a 3rd column as follows it fails to convert:
SELECT
MtgeLoanAmount
, CAST(convert(numeric(15,2),'1218300.00') as int) as TrialValue
, CAST(convert(numeric(15,2),MtgeLoanAmount) as int)
FROM dbo.Processed_VA_From_Excel
where
FipsStateCode='06'
and FipsCountyCode='013'
and GuarantyAmount = '304575'
returns this:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
This may work for you:
SELECT
MtgeLoanAmount,
CONVERT(INT, ROUND(MtgeLoanAmount, 0)) AS MtgeLoanAmountNoCents
FROM
dbo.Processed_VA_From_Excel
WHERE
FipsStateCode = '06' AND
FipsCountyCode = '013' AND
GuarantyAmount = '304575'

"Cursor type changed" error on Perl OLE32 MSSQL dateadd function results

The following sql "select DATEADD(day, DATEDIFF(day, 2, GETDATE()), '20:00:00') as A" runs perfectly fine in Microsoft sql query.
However in perl, it complains with the following error "Description: [Microsoft][ODBC SQL Server Driver]Cursor type changed".
I double checked and my code can run select and update statements with no issues so I am a bit stumbled about the cursor error.
Note that I have not included my connection string but have illustrated that I am using win32::OLE.
use Win32::OLE;
$conn->{ConnectionString} = "...";
$conn->open; # open connection to the DB
$state = $conn ->state; #1 means connected
if($state ne "1"){...
$mssql_select = "select DATEADD(day, DATEDIFF(day, 2, GETDATE()), '20:00:00')
as A";
$rs->Open( $mssql_select, $conn);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
my ($is_message, $real_error_found);
foreach my $error (in $error_collection)
{
#output error statements
$is_message = ($error->{SQLState} eq "01000" && $error->{NativeError}==0);
$real_error_found=1 unless $is_message;
$status = "ERROR # " . $error->{Number}
. "\n Description: " . $error->{Description}
. "\nSource: " . $error->{Source} . "\n";
}
Results in "Description: [Microsoft][ODBC SQL Server Driver]Cursor type changed".
Any brainstormnig ideas the group can provide would be appreciated.
I figured it out, see below
Solved it, turns out this is just a warning, sql server does not know what type of cursor will be returned, the results actually get returned. See http://social.msdn.microsoft.com/Forums/sqlserver/en-US/e15141e7-3084-487d-a60f-47afac046a55/odbcsql-cursor-error

Error using to_char // to_timestamp

I have a database in PostgreSQL and I'm developing an application in PHP using this database.
The problem is that when I execute the following query I get a nice result in phpPgAdmin but in my PHP application I get an error.
The query:
SELECT t.t_name, t.t_firstname
FROM teachers AS t
WHERE t.id_teacher IN (
SELECT id_teacher FROM teacher_course AS tcourse
JOIN course_timetable AS coursetime
ON tcourse.course = coursetime.course
AND to_char(to_timestamp('2010-4-12', 'YYYY-MM-DD'),'FMD') = (coursetime.day +1)
)
AND t.id_teacher NOT IN (
SELECT id_teacher FROM teachers_fill WHERE date = '2010-4-12'
)
ORDER BY t.t_name ASC
And this is the error in PHP
operator does not exist: text = integer (to_timestamp('', 'YYYY-MM-DD'),'FMD') =
(courset... ^ HINT: No operator matches the given name and argument type(s).
You might need to add explicit type casts.
The purpose to solve this error is to use the ORIGINAL query in php with :
$date = "2010"."-".$selected_month."-".$selected_day;
SELECT ...
AND to_char(to_timestamp('$date', 'YYYY-MM-DD'),'FMD') = (coursetime.day +1)
)
AND t.id_teacher NOT IN (
SELECT id_teacher FROM teachers_fill WHERE date = '$date'
)
The error message seems quite clear to me. You are mixing strings and numbers. More precisely, you are converting a string ('2010-4-12') to a timestamp, then to a string, then comparing to an int. This is a type mess, and postgresql is quite strict with typing (for good reasons). What are you trying to do here ?
to_char(to_timestamp('2010-4-12', 'YYYY-MM-DD'),'FMD') = (coursetime.day +1))
Further, you should use a TIMESTAMP, just a DATE.
If (I'm not sure) you are tring to compare the day of week from a date formated as 'YYYY-MM-DD' to a given value (as an integer), you should better use date_part. For example (not tested):
date_part('dow' , to_date('2010-4-12', 'YYYY-MM-DD') ) = coursetime.day + 1

Resources