The whole problem comes down to this: does the client (DBD::ODBC in this case) get a description of the datatypes for each of the placeholders? If it does, then it can "know" that the data that you pass in should be converted to MONEY (or NUMERIC, or whatever). If it doesn't, then you have to supply that information - hence the call to
$sth->bind_param(1, 7, SQL_NUMERIC) to let the driver know that the data needs to be passed as numeric data.
Michael