如何使用 SQLite 使 DBIx::Class 忽略 ORDER BY 中的大小写?
How do I make DBIx::Class ignore case in ORDER BY with SQLite?
通常 SQLite 的排序规则区分大小写。所有大写字母都在小写字母之前。但是可以在 ORDER BY
子句中告诉 SQLite 忽略它,by doing this:
... ORDER BY foo COLLATE NOCASE ASC
但是我们如何用 DBIx::Class 做到这一点?
考虑以下示例,它在内存中部署了一个 SQLite 数据库,其中包含 table foo
和一个 bar
comlumn。连接使用the quote_names
setting. It fills in the values z Z b B a A
and then gets them back out using all
on the ResultSet. I'll be using this setup in all my following examples. You need DBIx::Class and DBD::SQLite到运行这个。
use strict;
use warnings;
package Foo::Schema::Result::Foo;
use base 'DBIx::Class::Core';
__PACKAGE__->table("foo");
__PACKAGE__->add_columns( "bar", { data_type => "text" }, );
package Foo::Schema;
use base 'DBIx::Class::Schema';
__PACKAGE__->register_class( 'Foo' => 'Foo::Schema::Result::Foo' );
package main;
my $schema = Foo::Schema->connect(
{
dsn => 'dbi:SQLite:dbname=:memory:',
quote_names => 1,
}
);
$schema->deploy;
$schema->resultset('Foo')->create( { bar => $_ } ) for qw(z Z b B a A);
my @all = $schema->resultset('Foo')->search(
{},
{
order_by => { -asc => 'me.bar' },
},
)->all;
# example code starts here
print join q{ }, map { $_->bar } @all;
此输出区分大小写。
A B Z a b z
现在我当然可以用 Perl 对其进行排序并使其不区分大小写,就像这样。
print join q{ }, sort { lc $a cmp lc $b } map { $_->bar } @all;
现在我得到
A a B b Z z
但如果我直接使用底层 DBI 句柄进行查询,我也可以使用 COLLATE NOCASE
。
$schema->storage->dbh_do(
sub {
my ( $storage, $dbh, @args ) = @_;
my $res = $dbh->selectall_arrayref(
"SELECT * FROM foo ORDER BY bar COLLATE NOCASE ASC"
);
print "$_->[0] " for @$res;
}
这给了我们
a A b B z Z
我希望 DBIC 使用 COLLATE NOCASE
,但没有 运行ning 任何 SQL。我不想在 ORDER BY
中进行任何昂贵的字符串转换,或稍后在 Perl 中进行。
如何在使用 SQLite 订购时告诉 DBIx::Class 使用 COLLATE NOCASE
?
以下不起作用:
order_by => { '-collate nocase asc' => 'me.bar' },
这只有在 quote_names
未打开时才有效。
order_by => { -asc => 'me.bar COLLATE NOCASE' },
它将使用上面的示例代码生成此查询和错误消息。
SELECT "me"."bar" FROM "foo" "me" ORDER BY "me"."bar COLLATE NOCASE"
ASC: DBIx::Class::Storage::DBI::_prepare_sth(): DBI Exception:
DBD::SQLite::db prepare_cached failed: no such column: me.bar COLLATE
NOCASE [for Statement "SELECT "me"."bar" FROM "foo" "me" ORDER BY
"me"."bar COLLATE NOCASE" ASC"]
或者我可以通过使用 DBIC 在 ORDER BY
子句中转换为 upper
或 lower
来实现。
my @all = $schema->resultset('Foo')->search(
{},
{
order_by => { -asc => 'lower(me.bar)' },
},
)->all;
print join q{ }, map { $_->bar } @all;
这给出了
a A b B z Z
without quote_names
这很相似,但相反。 (这不是我关心的问题),但在打开 quote_names
时也会抛出错误。
SELECT "me"."bar" FROM "foo" "me" ORDER BY "lower(me"."bar)" ASC:
DBIx::Class::Storage::DBI::_prepare_sth(): DBI Exception:
DBD::SQLite::db prepare_cached failed: no such column: lower(me.bar)
[for Statement "SELECT "me"."bar" FROM "foo" "me" ORDER BY
"lower(me"."bar)" ASC"]
如果您愿意使用非常少量的 SQL,您可以传递一个标量引用来表示文字 SQL,DBIC 不会弄乱它:
order_by => \'me.bar COLLATE NOCASE ASC'
或者,仅使用最少量的文字 SQL:
order_by => { -asc => \'me.bar COLLATE NOCASE' }
请注意,此语法是 technically discouraged,但我不知道有任何其他方法可以实现您所追求的目标:
The old scalarref syntax (i.e. order_by => \'year DESC') is still
supported, although you are strongly encouraged to use the hashref
syntax as outlined above.
通常 SQLite 的排序规则区分大小写。所有大写字母都在小写字母之前。但是可以在 ORDER BY
子句中告诉 SQLite 忽略它,by doing this:
... ORDER BY foo COLLATE NOCASE ASC
但是我们如何用 DBIx::Class 做到这一点?
考虑以下示例,它在内存中部署了一个 SQLite 数据库,其中包含 table foo
和一个 bar
comlumn。连接使用the quote_names
setting. It fills in the values z Z b B a A
and then gets them back out using all
on the ResultSet. I'll be using this setup in all my following examples. You need DBIx::Class and DBD::SQLite到运行这个。
use strict;
use warnings;
package Foo::Schema::Result::Foo;
use base 'DBIx::Class::Core';
__PACKAGE__->table("foo");
__PACKAGE__->add_columns( "bar", { data_type => "text" }, );
package Foo::Schema;
use base 'DBIx::Class::Schema';
__PACKAGE__->register_class( 'Foo' => 'Foo::Schema::Result::Foo' );
package main;
my $schema = Foo::Schema->connect(
{
dsn => 'dbi:SQLite:dbname=:memory:',
quote_names => 1,
}
);
$schema->deploy;
$schema->resultset('Foo')->create( { bar => $_ } ) for qw(z Z b B a A);
my @all = $schema->resultset('Foo')->search(
{},
{
order_by => { -asc => 'me.bar' },
},
)->all;
# example code starts here
print join q{ }, map { $_->bar } @all;
此输出区分大小写。
A B Z a b z
现在我当然可以用 Perl 对其进行排序并使其不区分大小写,就像这样。
print join q{ }, sort { lc $a cmp lc $b } map { $_->bar } @all;
现在我得到
A a B b Z z
但如果我直接使用底层 DBI 句柄进行查询,我也可以使用 COLLATE NOCASE
。
$schema->storage->dbh_do(
sub {
my ( $storage, $dbh, @args ) = @_;
my $res = $dbh->selectall_arrayref(
"SELECT * FROM foo ORDER BY bar COLLATE NOCASE ASC"
);
print "$_->[0] " for @$res;
}
这给了我们
a A b B z Z
我希望 DBIC 使用 COLLATE NOCASE
,但没有 运行ning 任何 SQL。我不想在 ORDER BY
中进行任何昂贵的字符串转换,或稍后在 Perl 中进行。
如何在使用 SQLite 订购时告诉 DBIx::Class 使用 COLLATE NOCASE
?
以下不起作用:
order_by => { '-collate nocase asc' => 'me.bar' },
这只有在 quote_names
未打开时才有效。
order_by => { -asc => 'me.bar COLLATE NOCASE' },
它将使用上面的示例代码生成此查询和错误消息。
SELECT "me"."bar" FROM "foo" "me" ORDER BY "me"."bar COLLATE NOCASE" ASC: DBIx::Class::Storage::DBI::_prepare_sth(): DBI Exception: DBD::SQLite::db prepare_cached failed: no such column: me.bar COLLATE NOCASE [for Statement "SELECT "me"."bar" FROM "foo" "me" ORDER BY "me"."bar COLLATE NOCASE" ASC"]
或者我可以通过使用 DBIC 在 ORDER BY
子句中转换为 upper
或 lower
来实现。
my @all = $schema->resultset('Foo')->search(
{},
{
order_by => { -asc => 'lower(me.bar)' },
},
)->all;
print join q{ }, map { $_->bar } @all;
这给出了
a A b B z Z
without quote_names
这很相似,但相反。 (这不是我关心的问题),但在打开 quote_names
时也会抛出错误。
SELECT "me"."bar" FROM "foo" "me" ORDER BY "lower(me"."bar)" ASC: DBIx::Class::Storage::DBI::_prepare_sth(): DBI Exception: DBD::SQLite::db prepare_cached failed: no such column: lower(me.bar) [for Statement "SELECT "me"."bar" FROM "foo" "me" ORDER BY "lower(me"."bar)" ASC"]
如果您愿意使用非常少量的 SQL,您可以传递一个标量引用来表示文字 SQL,DBIC 不会弄乱它:
order_by => \'me.bar COLLATE NOCASE ASC'
或者,仅使用最少量的文字 SQL:
order_by => { -asc => \'me.bar COLLATE NOCASE' }
请注意,此语法是 technically discouraged,但我不知道有任何其他方法可以实现您所追求的目标:
The old scalarref syntax (i.e. order_by => \'year DESC') is still supported, although you are strongly encouraged to use the hashref syntax as outlined above.