我的希望是DBI::sql_type_cast
DBIstcf_DISCARD_STRING
- 标志会将$ sv从'4.8g'修改为4.8。
(DBIstcf_DISCARD_STRING
:
“如果指定了这个标志,那么当驱动程序成功地将绑定的perl标量转换为非字符串类型时,标量的字符串部分将被丢弃。”)
返回值sv could not be case and DBIstcf_STRICT was not used
是什么意思?
#!/usr/bin/env perl
use warnings;
use 5.012;
use DBI qw(:sql_types);
my $dsn = "DBI:Proxy:hostname=horst;port=2000;dsn=DBI:ODBC:db1.mdb";
my $dbh = DBI->connect( $dsn, undef, undef, { RaiseError => 1, PrintError => 0 } )
or die $DBI::errstr;
my $sv = '4.8g';
my $sql_type = SQL_DOUBLE;
my $flags = DBIstcf_DISCARD_STRING;
my $sts = DBI::sql_type_cast( $sv, $sql_type, $flags );
say $sts; # 1 (sv could not be case and DBIstcf_STRICT was not used)
say $sv;
# Argument "4.8b" isn't numeric in subroutine entry at ./perl6.pl line 14.
# 1
# 4.8b
答案 0 :(得分:5)
文档中包含一个拼写错误 - $sts
== 1的描述应为“sv无法强制转换” - 即转换为{{1}你所提供的价值是不可能的,所以什么都没做。
SQL_DOUBLE
意味着与您想要的不同。在Perl内部术语中,这意味着如果您通过带有DBIstcf_DISCARD_STRING
和POK
以及PV部分NOK
和NV部分"1.23"
的SV,您将获得带有{{的SV 1}}和1.23
以及NV部分!POK
- 也就是说,标量的存储字符串部分将无效,数字部分保持不变,因此将来尝试将标量用作字符串将强制它从数字重新转换为字符串。但请注意,它表示只有如果演员表成功才会发生,如果该值不是一个有效的数字,则NOK
的演员表不会成功。 “4.8g”未通过测试。
您只需执行1.23
清除SQL_DOUBLE
并强制执行$sv = 0 + $sv;
,就可以自行清除值几乎的字符串部分与DBI一样有效以相同的方式重新转换为字符串。这与DBI之间的区别在于,它实际上并不像DBI那样清除 PV,只是标记它无效。要以与DBI相同的方式立即强制值清除,您需要执行类似
POK
但除非你有一些非常好的解释,为什么你需要它,你没有 - 所以不要使用它。 :)
答案 1 :(得分:1)
阅读文档和DBI.xs中的代码(实现在sql_type_cast_svpv
中)之后,返回值1意味着“无法正确地转换值并且未使用DBIstcf_STRICT”。
在你的情况下,取决于该功能的关键部分:
case SQL_DOUBLE:
sv_2nv(sv);
/* SvNOK should be set but won't if sv is not numeric (in which
* case perl would have warn'd already if -w or warnings are in effect)
*/
cast_ok = SvNOK(sv);
break;
....
if (cast_ok) {
if (flags & DBIstcf_DISCARD_STRING
&& SvNIOK(sv) /* we set a numeric value */
&& SvPVX(sv) /* we have a buffer to discard */
) {
SvOOK_off(sv);
if (SvLEN(sv))
Safefree(SvPVX(sv));
SvPOK_off(sv);
SvPV_set(sv, NULL);
SvLEN_set(sv, 0);
SvCUR_set(sv, 0);
}
}
if (cast_ok)
return 2;
应该为你设置SvNOK。如果不深入研究sv_2nv,问题的核心是“4.8g”不是数字类型,因为标量值中的数字标志未设置(这是SvNOK检查的)。
我的建议是,在调用sql_type_cast之前使用正则表达式去除该输入。
答案 2 :(得分:0)
文档中的拼写错误现已在subversion主干中修复。
以下是为什么添加sql_type_cast的简要说明。
虽然没有什么可以阻止你使用sql_type_cast,但它是专门为驱动程序(DBD)添加的,用于转换从数据库返回的数据。它解决的原始问题是整数主要绑定为字符串,因此当从数据库返回数据时,标量的pv被设置。像JSON :: XS这样的模块很聪明,看一下pv来帮助确定标量是否是一些不是。没有sql_type_cast,JSON :: XS正在转换包含1的标量但pv设置为“1”而不是JSON转换中的较短1。
据我所知,只有DBD :: Oracle现在才这样做,尽管它在DBD :: ODBC的TODO中。