2017-01-12 27 views
1

Я не могу понять, что я делаю неправильно здесь. У меня есть следующие значения для этих переменных.Почему я получаю «Ошибка конверсии при преобразовании даты и/или времени из символьной строки» при вычитании числа из GETDATE()?

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; 

И когда я пытаюсь запустить selectrow_array на SQL, как например:

my $qnCount = $dbh->selectrow_array($sql, undef, $argsRef->{lookBack}); 

Я получаю следующее сообщение об ошибке:

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() - ?) 
"] 

Итак, это мое понимание того, что третья параметр в вызове selectrow_array из дескриптора базы данных должен быть переменными связывания. Тем не менее, они, похоже, не является обязательным ....

ручка базы данных создаются как таковые:

my $dbh = DBI->connect_cached("dbi:ODBC:$dsn", undef, undef, { 
    PrintError => 0, 
    RaiseError => 1, 
    ShowErrorStatement => 1, 
    LongReadLen => 500000, 
}) 

$dsn является правильным DSN, но не показан, по разным причинам, но мы знаем, что это работает граждение сообщение об ошибке, возвращаемое с SQL Server.

Любая идея, что я делаю неправильно?

Заранее за вашу помощь.

+0

Я предполагаю, что запрос должен быть '(GETDATE() - 30)'; заполнители цитируются по умолчанию, так что вы фактически получаете '(GETDATE() - '30')'. Посмотрите раздел «Типы данных для заполнителей» в [DBI docs] (https://metacpan.org/pod/DBI#bind_param) и [DBD :: ODBC docs] (https://metacpan.org/pod/DBD :: ODBC# Binding-Columns). – ThisSuitIsBlackNot

+1

Ну, начните с [используя 'DATEADD()' вместо сокращенного] (http://sqlblog.com/blogs/aaron_bertrand/archive/2011/09/20/bad-habits-to-kick-using-shorthand-with -date-время operations.aspx). Также часть о $ dsn и подключении к базе данных была скопирована из другого вопроса и здесь не уместна. –

+0

Это не похоже на проблему с Perl или DBI, скорее ваш запрос на дату выглядит неправильно. Рассмотрите возможность использования 'dateadd' для вычитания дней из' getdate' http://stackoverflow.com/questions/27247770/how-to-subtract-30-days-from-the-current-date-using-sql-server –

ответ

2

Во-первых, выкрикнуть на ThisSuitIsBlackNot, чтобы указать на проблему. Я сделал предположение, что DBI/driver сможет определить тип значения. Это было неправильно. Итак, я прямо указал тип:

$sth = $dbh->prepare($sql); 
$sth->bind_param(1, ($argsRef->{lookBack} * -1), { TYPE => SQL_INTEGER });  
$sth->execute(); 
my $qnCount = $sth->fetchrow_array(); 

Это позволило ему пройти как целое число, и SQL работал без проблем.

В случае, если вам интересно, почему я умножения на -1, это потому, что я изменил запрос на использование DATEADD:

SELECT COUNT(*) 
FROM tableName u 
WHERE 1=1 AND u.ManufacturerPartNumber IN ('x') 
AND CAST(u.InspectionStartDate AS DATETIME) > DATEADD(dd, ?, GETDATE()) 

Хотя, как представляется, некоторые продолжают обсуждение в отношении его использования, то есть здесь работает.

Благодарим всех вас за помощь.

+0

Я бы также предложил 'DAY' вместо' dd', чтобы быть более наглядным. Никто не собирается считать, что 'dd' означает' month', но попробуйте 'y' против' YEAR' и 'w' против' WEEK'. Другой случай, когда несколько нажатий клавиш дают огромные дивиденды. –

+0

@AaronBertrand Полезно знать. Спасибо Аарону. К сожалению, у моих знаний SQL Server все еще есть возможность пойти, но всегда полезно улучшить его. – FrankRalphBob

 Смежные вопросы

  • Нет связанных вопросов^_^