2017-01-12 7 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; 

そして、私は、このようなようなSQLでselectrow_arrayを実行しよう:

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ドキュメント](https://metacpan.org/pod/DBI#bind_param)と[DBD :: ODBCドキュメント](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-time-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

まず、ThisSuitIsBlackに叫んで、問題を指摘してください。私は、DBI /ドライバが値の型を決定できると仮定しました。それは間違っていた。だから、私は明示的に型を述べました:

これは、これが整数として通過することができ、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

私は 'dd'の代わりに' DAY'を提案しています。誰も 'dd'は' month'を意味するとは思っていませんが、 'y'と' YEAR'と 'w''と' WEEK'を試してみてください。いくつかのキーストロークが大きな配当を支払う別のケース。 –

+0

@AaronBertrandお役立ち情報アロンに感謝します。残念ながら、私のSQL Serverの知識にはまだ方法がありますが、それを改善するのは常に良い方法です。 – FrankRalphBob

関連する問題