在 sqlite3 中修改列的类型

Posted

技术标签:

【中文标题】在 sqlite3 中修改列的类型【英文标题】:Modify a Column's Type in sqlite3 【发布时间】:2011-01-06 05:07:57 【问题描述】:

我对 SQLite 3 还很陌生,刚才我不得不在现有的表中添加一列。我是这样做的:ALTER TABLE thetable ADD COLUMN category;

当然,我忘了指定该列的类型。我想做的第一件事就是删除该列,然后重新添加它。但是,SQLite 似乎没有一种简单的方法来做到这一点,我不得不备份表并在没有列的情况下重新创建它。

这看起来很乱,我想知道是否只有一种修改/添加列类型的方法。我想是这样,但是我的搜索没有产生任何结果,因为我是 SQLite 的新手,我想这是由于我在查询中的措辞不正确。

【问题讨论】:

也许对其他想知道如何避免这种情况的人有所帮助...在列名之后指定列特征。一个例子:ALTER TABLE thetable ADD COLUMN thenewcolumn INTEGER DEFAULT 0. SQLite 现在的 ALTER 功能有限:sqlite.org/lang_altertable.html 【参考方案1】:

SQLite 不支持删除或修改列,apparently。但请记住 SQLite 中的列数据类型为 aren't rigid。

另见:

SQLite Modify Column

【讨论】:

所以如果我没有定义类型,我应该仍然可以在其中插入文本吗?当然,稍后当我部署到生产环境时,我会明确说明类型(文本),但现在我应该没问题? 是的。您也可以在该列中插入非文本值:“SQLite 使用更通用的动态类型系统。在 SQLite 中,值的数据类型与值本身相关联,而不是与其容器相关联。” (来自我的第二个链接)指定列的类型在 SQLite 中的重要性远低于其他 RDBM。 这是真的...但是如果您稍后使用您将使用的数据类型创建其他表,那么您的连接查询将无法使用索引,因为列不会具有相同的类型 列上没有类型也会导致 where 子句出现问题。例如,如果您声明一个没有类型的 _id 列,则使用占位符(例如,where _id=?)的 where 子句将永远不会返回任何行,因为最终查询将使用 where _id='1' 而 SQLite 不知道该怎么做比较恰当。它将两者作为字符串(来自 where 子句)和整数(来自行数据)进行比较,并且每次都会为 false。省略列类型似乎是一个很大的疏忽,但 SQLite 允许它似乎是一个更大的疏忽。 那么如果你定义一个列类型为INT那么你可以在里面插入VARCHAR的值吗?【参考方案2】:

如果您更喜欢 GUI,DB Browser for SQLite 只需点击几下即可完成。

    “文件”-“打开数据库” 在“数据库结构”选项卡中,单击表内容(不是表名),然后单击“编辑”菜单,“修改表”,现在您可以通过下拉菜单更改任何列的数据类型。我将“文本”字段更改为“数字”,以便检索数字范围内的数据。

用于 SQLite 的 DB Browser 是开源且免费的。对于 Linux,它可以从存储库中获得。

【讨论】:

点击表格内容(不是表格名称)”是什么意思?在“数据库结构”选项卡下,我确实必须单击 Tables --> Mytable 下的表名。我还可以右键单击表格名称以弹出一个弹出菜单,您可以在其中选择“修改表格”。 在尝试对现有 sqlite 数据库进行任何 DB Browser 表修改之前备份您的数据库:github.com/sqlitebrowser/sqlitebrowser/issues/1481 在较新的版本中,该菜单中似乎不存在此选项......也许它已被删除 澄清原始答案和几个问题。截至 5/2021,修改表选项仍然存在。如果您单击相关表的“架构”列,然后转到编辑菜单,您将找到修改表选项。但是,请注意,如果您在相关表上定义了视图,则此方法无法正常工作,因为该工具通过复制和重新创建表来执行此操作。【参考方案3】:

可以通过重新创建表格。它对我的工作请按照以下步骤操作:

    使用 as select * from your table 创建临时表 删除表,使用修改列类型创建表 现在将临时表中的记录插入到新创建的表中 删除临时表

在工作线程中执行上述所有步骤以减少 uithread 上的负载

【讨论】:

我想知道,如果您可以将代码添加到您的答案中,好吗? 这是一个例子:CREATE TABLE temp AS select a, b, c, CAST(d AS INTEGER) AS d_new from original;以后删除不需要的东西【参考方案4】:

有一个更简单的方法:

ALTER TABLE your_main_table ADD COLUMN new_column_name new_column_data_type
UPDATE your_main_table SET new_column_name = CAST(old_column_name as new_data_type_you_want)

我在本地机器上试过这个,它可以工作

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案5】:

可以通过转储、编辑和重新导入表格来实现。

此脚本将为您完成(根据您的需要调整脚本开头的值):

#!/bin/bash

DB=/tmp/synapse/homeserver.db
TABLE="public_room_list_stream"
FIELD=visibility
OLD="BOOLEAN NOT NULL"
NEW="INTEGER NOT NULL"
TMP=/tmp/sqlite_$TABLE.sql

echo "### create dump"
echo ".dump '$TABLE'" | sqlite3 "$DB" >$TMP

echo "### editing the create statement"
sed -i "s|$FIELD $OLD|$FIELD $NEW|g" $TMP

read -rsp $'Press any key to continue deleting and recreating the table $TABLE ...\n' -n1 key 

echo "### rename the original to '$TABLE"_backup"'"
sqlite3 "$DB" "PRAGMA busy_timeout=20000; ALTER TABLE '$TABLE' RENAME TO '$TABLE"_backup"'"

echo "### delete the old indexes"
for idx in $(echo "SELECT name FROM sqlite_master WHERE type == 'index' AND tbl_name LIKE '$TABLE""%';" | sqlite3 $DB); do
  echo "DROP INDEX '$idx';" | sqlite3 $DB
done

echo "### reinserting the edited table"
cat $TMP | sqlite3 $DB

【讨论】:

以上是关于在 sqlite3 中修改列的类型的主要内容,如果未能解决你的问题,请参考以下文章

c#如何修改DataTable里面的特定列的数据类型

【原】Oracle 如何修改列的数据类型

如何使用默认值修改列的数据类型

如何修改ORACLE中的数据类型

如何修改现有列的数据类型?

怎么修改datatable中某一列的值?