使用 SQLite ADO.Net 提供程序需要将 GUID 直接放入查询的Where子句中而不使用参数

发布于 2024-12-08 09:49:22 字数 1951 浏览 0 评论 0原文

有没有办法让 GUID 成为 SQL 查询本身的一部分而不使用参数?

让我准确解释一下我想要做什么以及为什么。我正在使用一个现有的应用程序,该应用程序使用 ADO.Net 创建并连接到 SQLite 数据库。当前数据库的结构和查询方法是可怕的。我正在从根本上重新设计它的工作原理。然而,这并不是一件能够很快完成的事情。虽然重新设计正在完成,但我遇到了需要创可贴解决方案的情况。需要注意的是,代码最初实现背后的推理是模糊的,并且似乎是由缺乏数据库知识的人构建的。重构整个数据库以不需要这种情况是最终的解决方案,但现在我只想在现有结构内工作。

数据库的设计依赖于 GUID 来唯一标识行。为了执行数据的过滤检索,系统动态构建一个命令,该命令具有列出应检索的 GUID 的 IN 子句。现在,通过使用 GUID 类型的参数将 GUID 插入到查询中,因此查询看起来像

SELECT * FROM data_table WHERE guid_col IN( ?, ?, ?, ?)

当我需要检索相对大量的信息时,问题就出现了。 SQLite 的单个查询参数限制为 1000 个。如果我需要传递超过 1000 个 GUID 来进行检索,查询就会中断。构建上述字符串时,它会循环遍历 GUID 列表以插入问号并创建参数。我对这个问题的创可贴解决方案是将 GUID 值直接插入到问号当前所在的位置,并放弃在查询中包含参数。毕竟,这是一种将参数用于不需要使用的目的的类型。

这个“解决方案”的问题是我似乎无法让 GUID 与列中的数据相匹配,即查询始终返回 null。我知道 GUID 不是 SQLite 的原生类型,它的底层实际上被表示为 BLOB(是的,我确信我们使用的是 BLOB 而不是字符串表示形式)。然而,我一直无法让查询正确执行。

到目前为止,我已经尝试了以下所有操作:

我尝试在 GUID 上调用 ToString(),因此查询看起来像

SELECT * FROM data_table WHERE guid_col IN
   ( 'b5080d4e-37c3-4286-9c3a-413e8c367f36', 'aa0ff789-3ce9-4552-9840-5ed4d73c1e2c')

我尝试在 GUID 上调用 ToString("N"),所以查询看起来像

SELECT * FROM data_table WHERE guid_col IN
  ( 'b5080d4e37c342869c3a413e8c367f36', 'aa0ff7893ce9455298405ed4d73c1e2c')

我尝试调用GUID 上的 ToString("B") 因此查询看起来像是

SELECT * FROM data_table WHERE guid_col IN
  ( '{b5080d4e-37c3-4286-9c3a-413e8c367f36}',
    '{aa0ff789-3ce9-4552-9840-5ed4d73c1e2c}')

我尝试在 GUID 上调用 ToByteArray() 并将结果放入查询中,方法是将每个字节添加到在每个字节上调用 ToString("X") 的字符串,以便查询看起来像

SELECT *来自 data_table WHERE guid_col IN ( '4ED8B5C33786429C3A413E8C367F36', '89F7FAAE93C524598405ED4D73C1E2C')

在阅读 SQLite 文档时,我读到以下内容“BLOB 文字是包含十六进制数据的字符串文字,前面带有单个“x”或“X”字符。如果我尝试将此应用于我的查询所以它看起来

SELECT * FROM data_table WHERE guid_col IN
    ( x'4ED8B5C33786429C3A413E8C367F36', x'89F7FAAE93C524598405ED4D73C1E2C')

我收到一条错误,指出“x”不是可识别的符号。

是否可以在不使用参数的情况下将 GUID 放入查询字符串中?

Is there anyway to just have the GUID be part of the SQL Query itself without using a parameter?

Let me explain exactly what I am trying to do and why. I am working with an existing application that uses an ADO.Net to create and connect to a SQLite database. The current structure of the database and the method for querying it are horrendous. I am in the midst of a redesign of how it works fundamentally. However, that is not something that can be accomplished quickly. While that redesign is being completed, I have a situation that needs a band-aid solution. As a heads up, the reasoning behind the initial implementation of the code is obscure and appears to have been built by someone who had little database knowledge. Refactoring the entire database to not need this situation is the ultimate solution, but for now I'm just looking to work within the existing structure.

The design of the database relies on GUID's to uniquely identify rows. To perform filtered retrieval of the data the system dynamically builds a command that has an IN clause listing the GUIDs that should be retrieved. Right now the GUIDs are inserted into the query by using a parameter with type GUID, so the query will look like

SELECT * FROM data_table WHERE guid_col IN( ?, ?, ?, ?)

The problem comes in when I need to retrieve a relatively large amount of information. SQLite has a limitation of a 1000 parameters in a single query. If I need to pass in more than a 1000 GUIDs for the retrieval the query will just break. When building the above string it loops over a list of GUID's to insert the question marks and create the paramters. My band-aid fix to the problem was going to be to have the GUID value directly inserted into where the question marks are currently and forego having parameters in the query. After all, its kind of using parameters for a purpose they don't need to be used for.

The problem with this 'solution' is that I can't seem to get the GUID to match the data in the column i.e. the query is always returning null. I understand that GUIDs are not a native type to SQLite and underneath it is actually being represented as a BLOB (yes I am sure we are using the BLOB and not the string representation). Yet, I've been unable to get the query to execute correctly.

I've tried all the following so far:

I've tried calling ToString() on the GUID so the query looks like

SELECT * FROM data_table WHERE guid_col IN
   ( 'b5080d4e-37c3-4286-9c3a-413e8c367f36', 'aa0ff789-3ce9-4552-9840-5ed4d73c1e2c')

I've tried calling ToString("N") on the GUID so the query looks like

SELECT * FROM data_table WHERE guid_col IN
  ( 'b5080d4e37c342869c3a413e8c367f36', 'aa0ff7893ce9455298405ed4d73c1e2c')

I've tried calling ToString("B") on the GUID so the query looks like

SELECT * FROM data_table WHERE guid_col IN
  ( '{b5080d4e-37c3-4286-9c3a-413e8c367f36}',
    '{aa0ff789-3ce9-4552-9840-5ed4d73c1e2c}')

I've tried calling ToByteArray() on the GUID and putting the result into the query by adding each byte to the string calling ToString("X") on each byte so the query looks like

SELECT * FROM data_table WHERE guid_col IN
( '4ED8B5C33786429C3A413E8C367F36', '89F7FAAE93C524598405ED4D73C1E2C')

In reading the SQLite documentation I read the following "BLOB literals are string literals containing hexadecimal data and preceded by a single "x" or "X" character. If I try to apply this to my query so it looks like

SELECT * FROM data_table WHERE guid_col IN
    ( x'4ED8B5C33786429C3A413E8C367F36', x'89F7FAAE93C524598405ED4D73C1E2C')

I get an error saying that "x" is not a recognized symbol.

Is it possible to get the GUID into the query string without the use of the parameter?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笛声青案梦长安 2024-12-15 09:49:22

我建议您使用临时表来完成类似的事情。例如...

PRAGMA temp_store = MEMORY;

CREATE TEMP TABLE tbl_guids (guid_col text);

INSERT INTO tbl_guids VALUES ('b5080d4e-37c3-4286-9c3a-413e8c367f36');
INSERT INTO tbl_guids VALUES ('aa0ff789-3ce9-4552-9840-5ed4d73c1e2c');
... more inserts ...

SELECT * FROM data_table WHERE guid_col IN ( SELECT guid_col FROM tbl_guids);

DROP TABLE tbl_guids;

确保包装一个事务围绕所有< code>INSERT INTO 语句。这将极大地提高性能。 SQLite还允许临时表通过设置PRAGMA temp_store完全存在于内存中 = MEMORY

如果有多个用户同时访问该表并共享同一连接,则需要为临时表创建一些唯一性,例如向表名称添加随机数,例如tbl_guiids_9087

I suggest that you use a temporary table for something like this. For example...

PRAGMA temp_store = MEMORY;

CREATE TEMP TABLE tbl_guids (guid_col text);

INSERT INTO tbl_guids VALUES ('b5080d4e-37c3-4286-9c3a-413e8c367f36');
INSERT INTO tbl_guids VALUES ('aa0ff789-3ce9-4552-9840-5ed4d73c1e2c');
... more inserts ...

SELECT * FROM data_table WHERE guid_col IN ( SELECT guid_col FROM tbl_guids);

DROP TABLE tbl_guids;

Make sure to wrap a transaction around all of the INSERT INTO statements. This will help with performance by a ton. Also SQLite allows for temp tables to exist entirely in memory by setting PRAGMA temp_store = MEMORY

If you have a multiple users accessing the table at the same time sharing the same connection, you will need to create some uniqueness with the temp table such as adding a random number to the table name such as tbl_guids_9087.

家住魔仙堡 2024-12-15 09:49:22

如果在连接字符串中设置“BinaryGuid=False”,则可以将 GUID 作为字符串传递。
如果这样做了,“ToString()”应该可以正常工作。

You can pass GUID's in as strings if you set "BinaryGuid=False" in the connection string.
If this is done, "ToString()" should work fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文