objective-c - 直接通过名称绑定(bind) SQLite 参数

标签 objective-c ios xcode sqlite parameters

我最近 - 非常最近 - 开始学习如何为 iOS 编程,并且被 SQLite3 中似乎(对我来说)明显的疏忽所困扰。让我来证明一下,在上周之前我对 Mac、Objective C、Xcode、iOS 或 SQLite 的(实践)经验为零,所以我没有妄想进入久经考验的工具领域并发现明显的错误在我的第一次尝试中。我认为有一个很好的解释。

然而,在过去几个月使用 SQL Server、MySQL 和 PostgreSQL 之后,我惊讶地发现 SQLite 没有更好的按名称添加参数的功能。我可以在网上找到的所有内容(文档、论坛 [包括 SO])都说使用整数索引分配参数,如果您修改查询,这似乎很难维护。即使您可以在语句中命名参数并执行类似

的操作
sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@my_param"), myInt);

似乎也没有人这样做。事实上,似乎根本没有人尝试将其自动化;唯一alternate approach我可以找到使用的参数数组和循环计数器,并检查每个参数以确定要插入的对象类型。我最初考虑过类似的方法,但是 a) 我老板的立场是数据库参数应该始终进行类型检查(我同意,尽管我意识到 SQLite 字段不是强类型的,而且我在技术上无论如何都可以做到),b) 它感觉像是一个不雅的 hack,并且 c) 我认为这种方法没有被广泛使用是有原因的。所以:

1) 为什么 SQLite 中没有接受参数名称(例如,'const char')的绑定(bind)方法?或者有没有我遗漏了什么?

2) 为什么似乎没有人使用像上面示例那样的方法?

我深入研究了源代码,认为我可以轻松地修改库或编写自己的(类型化的)类方法来为我执行上述操作,但我假设没有人构建它是有原因的进入 SQLite 呢。我唯一的猜测是,查找参数索引所需的额外内存和周期对于 [在此处插入 iDevice] 来说太宝贵了,不值得使用参数名称带来的便利。 . . ?

如有任何见解,我们将不胜感激。

最佳答案

  1. 有;这是 sqlite3_bind_parameter_index()您提到的用于将参数名称转换为索引的函数,然后您可以将其与 sqlite3_bind_*() 一起使用功能。但是,没有 sqlite3_bind_*_by_name() 函数或类似的东西。这是为了帮助防止 API 膨胀。人气Flying Meat Database sqlite wrapper如果您有兴趣了解它的使用方式,它的一个分支中支持命名参数。

    如果您考虑实现全命名参数绑定(bind)方法需要什么,请考虑当前的 bind 函数列表:

    int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
    int sqlite3_bind_double(sqlite3_stmt*, int, double);
    int sqlite3_bind_int(sqlite3_stmt*, int, int);
    int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
    int sqlite3_bind_null(sqlite3_stmt*, int);
    int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
    int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
    int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
    int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
    

    如果我们想添加对命名参数的显式支持,该列表的长度将加倍以包括:

    int sqlite3_bind_name_blob(sqlite3_stmt*, const char*, const void*, int n, void(*)(void*));
    int sqlite3_bind_name_double(sqlite3_stmt*, const char*, double);
    int sqlite3_bind_name_int(sqlite3_stmt*, const char*, int);
    int sqlite3_bind_name_int64(sqlite3_stmt*, const char*, sqlite3_int64);
    int sqlite3_bind_name_null(sqlite3_stmt*, const char*);
    int sqlite3_bind_name_text(sqlite3_stmt*, const char*, const char*, int n, void(*)(void*));
    int sqlite3_bind_name_text16(sqlite3_stmt*, const char*, const void*, int, void(*)(void*));
    int sqlite3_bind_name_value(sqlite3_stmt*, const char*, const sqlite3_value*);
    int sqlite3_bind_name_zeroblob(sqlite3_stmt*, const char*, int n);
    

    两倍的功能意味着更多的时间花在维护 API、确保向后兼容性等方面。然而,通过简单地引入 sqlite3_bind_parameter_index(),他们能够添加对命名的完整支持只有一个单一函数的参数。这意味着如果他们决定支持新的绑定(bind)类型(可能是 sqlite3_bind_int128?),他们只需添加一个函数,而不是两个。

  2. 至于为什么似乎没有人使用它...我无法通过调查给出任何明确的答案。我的猜测 是按顺序引用参数更自然一些,在这种情况下命名参数就没那么有用了。命名参数似乎只有在您需要乱序引用参数时才有用。

关于objective-c - 直接通过名称绑定(bind) SQLite 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7508107/

相关文章:

objective-c - 如何以编程方式监视 KVC 对象?

ios - 在 Singleton 类中使用数组在 View Controller IOS 之间传递数据?

ios - UITableView didSelectRowAt 无法获取我的单元格

ios - UIView 只会动画一次

iphone - UITableView 无法一直滚动到底部

objective-c - Cocoa 程序退出没有崩溃

ios - 我需要我的日期/时间标签不包含日期。谁知道IOS怎么玩?

ios - 在应用程序终止后运行代码......可能吗? (Xcode 8, swift 3)

ios - 从 Swift 中的另一个类访问 ViewController 类

iphone - 如何将后置摄像头实时视频显示到 UIImageView?