【仓颉语言入门 · 第二篇 第 8 课】
【仓颉语言入门 · 第二篇 第 8 课】建表用代码定义表结构上一课我们连上了tumo_governance库但程序除了握手什么也没干——因为还不知道怎么让数据库干活。数据库里的活分两大类DDLData Definition Language定义表结构和DMLData Manipulation Language增删改查数据。这一课先学 DDL 里最核心的一件用仓颉代码执行CREATE TABLE亲手建出一张表。建表的语法不难难的是看懂一张真实表为什么这么设计——所以我们不从玩具表讲起直接从库里真实的sys_user表开刀。目录第二篇导航第一篇《仓颉语言入门》共 30 课已完结环境搭建 → 语法 → 函数 → 类型系统 → 工程化 → 并发 → 两场实战。第二篇在更高的起点上继续共26 课、4 个模块模块课次内容一、补遗篇0106正则、时间日期、命令行参数、随机数、加密哈希、二进制处理二、数据库篇0715入门与连接、建表、查询、插入、更新删除、预编译防注入、事务、手写 DAO、综合小实战三、进阶硬核篇1622反射、宏基础、deriving 实战、FFI 基础、FFI 进阶、并发容器、对象池四、实战项目篇2326HTTP 基础、HTTP 进阶、多线程日志分析器、简易爬虫正则表达式std.regex时间日期处理std.time命令行参数解析std.argopt随机数与概率std.random加密与哈希std.crypto二进制数据处理std.binary数据库入门认识 std.database.sql连上 MySQL建表用代码定义表结构本文查询SELECT 与结果集遍历插入INSERT、占位符与自增主键更新与删除UPDATE / DELETE预编译与防 SQL 注入事务批量操作的成败一致手写 DAO 数据访问层数据库综合小实战反射在运行时打量类型宏基础std.ast 与 quotederiving 宏实战与 C 互操作基础FFI 调用 C 函数FFI 进阶结构体、指针与编译配置并发容器并发安全的集合对象池与资源复用实战三HTTP 服务端基础实战四HTTP 进阶与 JSON 接口实战五多线程日志分析器实战六简易爬虫一、先看看真实的表长什么样建表之前先学会读表。打开 MySQL 命令行客户端mysql -u root -p看看上一课那个库里的用户表USEtumo_governance;DESCsys_user;DESCdescribe 的缩写用来查看一张表的结构定义输出如下------------------------------------------------------ | Field | Type | Null | Key | Default | Extra | ------------------------------------------------------ | id | bigint(20) | NO | PRI | NULL | | | tenant_id | bigint(20) | YES | | NULL | | | user_name | varchar(50) | YES | | NULL | | | nick_name | varchar(50) | YES | | NULL | | | password | varchar(100) | YES | | NULL | | | sex | int(11) | NO | | 1 | | | dept_id | bigint(20) | YES | | NULL | | | phone | varchar(15) | YES | | NULL | | | email | varchar(20) | YES | | NULL | | | avatar | varchar(200) | YES | | NULL | | | login_time | timestamp | YES | | NULL | | | user_status | int(11) | NO | | 1 | | | create_time | timestamp | YES | | NULL | | | create_by | varchar(32) | YES | | NULL | | | update_time | timestamp | YES | | NULL | | | update_by | varchar(32) | YES | | NULL | | | del_flag | int(11) | NO | | 1 | | ------------------------------------------------------一张表的结构就是若干列的定义每列六个属性列含义读法示例id 列Field列名idType数据类型bigint(20)大整数Null是否允许为空NO必须有值Key是否索引/主键PRI主键Default不写时的默认值sex默认 1Extra附加修饰空注意这里先把这张表的样子记在脑子里下面建我们自己的表时每个修饰词都能在这里找到对照。二、CREATE TABLE 逐行讲假设系统要记录谁、什么时候、从哪个 IP 登录过、成没成功——这类日志数据不该混在用户表里得单开一张sys_login_log登录日志表。建表语句如下CREATETABLEsys_login_log(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULL,login_ipVARCHAR(50),login_timeDATETIME,successINTNOTNULLDEFAULT1);一列一行每行都是同一个句式列名 类型 [约束…]。逐行拆解id BIGINT PRIMARY KEY AUTO_INCREMENT大整数主键AUTO_INCREMENT表示插入时不用给值数据库自动编号1、2、3……。回头看sys_user的id列——它的Extra是空的没有自增说明它的编号是程序自己算好再写入的真实项目常用分布式 ID。两种方式都合法我们练习表选自增最省心。user_id BIGINT NOT NULL这条日志属于哪个用户NOT NULL表示不允许空着——没主人的日志没意义。login_ip VARCHAR(50)变长字符串最长 50 个字符。不写NOT NULL就是默认可空。login_time DATETIME日期时间类型YYYY-MM-DD HH:MM:SS。sys_user里用的是TIMESTAMP两者都能存时间新手阶段知道都是时间即可。success INT NOT NULL DEFAULT 1是否登录成功1 成 0 败DEFAULT 1表示插入时没写这一列就自动填 1。常用 MySQL 类型先认这几个括号里是对应的仓颉类型下一课查询取数时真正用到现在混个眼熟MySQL 类型用途仓颉类型INT普通整数Int32BIGINT大整数主键常用Int64VARCHAR(n)变长字符串StringDATETIME/TIMESTAMP日期时间DateTimeDECIMAL(m,n)精确小数金额Decimal三、仓颉代码把建表语句发出去沿用上节课的cj_mysql_demo工程驱动、依赖都不动把src/main.cj改成package cj_mysql_demo import std.database.sql.* import mariadb.cdbc; main(): Int64 { let driver DriverManager.getDriver(mariadb).getOrThrow() let ds driver.open(mariadb://127.0.0.1:3306, [ (username, root), (password, wangpeng), (database, tumo_governance) ]) let conn ds.connect() // 建表 SQL定义登录日志表 let sql CREATE TABLE sys_login_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, login_ip VARCHAR(50), login_time DATETIME, success INT NOT NULL DEFAULT 1 ) let stmt conn.prepareStatement(sql) let result stmt.update() println(建表完成影响行数${result.rowCount}) stmt.close() conn.close() 0 }运行输出建表完成影响行数0四个要点DDL 走update()不走query()query()期待服务器返回一张结果表SELECT 才有建表没有结果表只有执行完毕的确认所以走update()通道。影响行数0不是失败update()返回的UpdateResult里有个rowCount属性表示这条 SQL 影响了多少数据行。建表动的是结构不是数据恒为 0。UpdateResult还有个lastInsertId属性那是第 10 课插入自增主键时才登场的角色。SQL 用三引号原样写仓颉的多行字符串让 SQL 保持原本的换行排版不用拼串可读性最好。Statement 也要 close和连接一样用完还回去。小提示编译时会看到warning: unused import mariadb.cdbc警告——这是正常的。这行 import 的价值在于触发驱动自注册第 7 课 FAQ 讲过编译器看不到包里的名字被直接使用才提醒忽略即可。四、再跑一次表已存在与 IF NOT EXISTS别改代码把上面的程序原样再跑一次这次程序直接抛异常An exception has occurred: SqlException: Table sys_login_log already exists, errorCode: 0下面还会跟着一串调用栈指明出错位置。服务器的态度很明确同名表已经存在拒绝再建。这在程序每次启动都要确保表存在的场景下很烦——总不能先人肉查一遍。SQL 早就备好了台阶CREATE TABLE IF NOT EXISTS存在就跳过、不存在才创建let stmt conn.prepareStatement( CREATE TABLE IF NOT EXISTS sys_login_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, login_ip VARCHAR(50), login_time DATETIME, success INT NOT NULL DEFAULT 1 ) ) let result stmt.update() println(建表完成影响行数${result.rowCount}) stmt.close()改完再跑无论跑几遍输出都恢复正常建表完成影响行数0记住这个搭配能重复执行的建表语句都该带上IF NOT EXISTS。五、验证成果然后收拾干净5.1 用客户端确认表真的建出来了代码说成功不算数亲眼看看。回到 MySQL 客户端DESCsys_login_log;------------------------------------------------------------- | Field | Type | Null | Key | Default | Extra | ------------------------------------------------------------- | id | bigint(20) | NO | PRI | NULL | auto_increment | | user_id | bigint(20) | NO | | NULL | | | login_ip | varchar(50) | YES | | NULL | | | login_time | datetime | YES | | NULL | | | success | int(11) | NO | | 1 | | -------------------------------------------------------------和我们写的定义一字不差id带上了auto_incrementsuccess默认值是 1。反过来表不存在时DESC会直接报错ERROR 1146 (42S02): Table tumo_governance.sys_login_log doesnt exist——所以能打出结构就是建成功了。5.2 DROP TABLE删表只需一句练习表不想留了删掉let stmt conn.prepareStatement(DROP TABLE IF EXISTS sys_login_log) let result stmt.update() println(删表完成影响行数${result.rowCount}) stmt.close()删表完成影响行数0和建表镜像DROP TABLE在表不存在时会报错加上IF EXISTS就可以放心重复执行。⚠️红线DROP TABLE删的是整张表连同里面的所有数据没有回收站、没有确认弹窗执行即消失。本课只允许删你自己刚建的练习表sys_login_logsys_user等库里已有的表一个都不许动。以后在任何真实项目里执行 DROP 前都默念三遍表名。六、常用 API 速查建表篇任务写法执行 DDLconn.prepareStatement(sql).update()建表可重复执行CREATE TABLE IF NOT EXISTS 表名 (...)删表可重复执行DROP TABLE IF EXISTS 表名看影响行数UpdateResult.rowCountDDL 恒为 0客户端看表结构DESC 表名客户端看完整建表语句SHOW CREATE TABLE 表名七、常见问题 FAQQ1建表明明成功了为什么 rowCount 是 0rowCount数的是受影响的数据行数DDL 改的是表结构不触碰数据行所以恒为 0。判断 DDL 成败的标准是没抛异常就是成功——失败时服务器会拒绝执行驱动抛出SqlException就像第四节的 already exists。Q2VARCHAR(50)的 50 是字符数还是字节数字符数。只要库是utf8mb4字符集一个中文、一个 emoji 都只算 1 个字符。这也是第 7 课坚持建库用utf8mb4的原因之一。Q3列名、表名能用中文吗语法上用反引号包住可以用户但强烈不建议不同数据库、不同工具链对中文标识符的支持参差不齐给自己挖坑。业界习惯是小写字母 下划线如sys_login_log。Q4INT和BIGINT怎么选主键、用户 ID 这类只涨不跌、可能很大的用BIGINT对应仓颉Int64年龄、状态这种小范围整数用INTInt32就够。拿不准就用BIGINT多几个字节换不越界值。八、课后练习前 3 题必做第 4 题选做。都在tumo_governance库里操作只许动自己建的练习表。第 1 题必做建一张操作日志表仿照课文在cj_mysql_demo工程里建一张sys_op_log操作日志表要求四列id自增主键、user_idBIGINT非空、op_descVARCHAR(200)操作描述、op_timeDATETIME。提示连接部分的代码与课文完全相同只换sql变量的内容执行用stmt.update()打印result.rowCount。期望输出建表完成影响行数0第 2 题必做亲手触发一次 already exists不改代码把第 1 题的程序再跑一次逐字读一遍报错应该看到SqlException: Table sys_op_log already exists然后给建表语句加上IF NOT EXISTS再跑一次确认不再报错。这道题的目的already exists 是建表最高频的报错提前见过、会修以后就永远难不倒你。第 3 题必做删掉它并确认它真的没了用DROP TABLE IF EXISTS sys_op_log删掉第 1 题建的表打印影响行数然后到 MySQL 客户端执行DESC sys_op_log;确认客户端报ERROR 1146 (42S02): Table tumo_governance.sys_op_log doesnt exist第 4 题选做读一份真实的建表语句在 MySQL 客户端执行SHOWCREATETABLEsys_user对照输出回答两个问题sys_user的id列和我们建的sys_login_log的id列差在哪个修饰词这张表的存储引擎ENGINE和字符集CHARSET分别是什么下节预告表有了可里面还是空的——sys_user里倒是躺着 9 行真实用户数据正等着被读。下一课查询SELECT 与结果集遍历——发出第一条 SELECT用next()一行行把数据搬进仓颉程序并处理数据库里的 NULL 到了仓颉怎么办。系列说明本系列基于 Windows 平台 CIDE 仓颉 SDK1.2.0编写。本文全部代码、运行输出与报错文案均已在 SDK 1.2.0 MySQL 5.7 环境下逐块编译运行、逐字实测如遇 SDK 版本差异导致的细节出入以你本地版本为准欢迎评论区交流。 遇到问题扫码联系作者跟着课程练习时如果在 SDK 安装、环境变量配置、编译报错或调试上卡住欢迎扫码加作者企业微信直接咨询请备注仓颉课程离线环境下图片可能加载不出来也可以在 CIDE 菜单Help ▸ 联系作者 / Contact中查看同一张二维码应用内置兜底图无需联网。 工具下载本系列全程使用的仓颉 IDE ——CIDE免费开源、社区版GitCode 仓库 / 安装包下载https://gitcode.com/wp_upala/cide打开页面后进入发行版Releases两种包任选其一安装版下载CIDE-版本-x64-Setup.exe双击安装适合日常长期使用免安装版Portable下载CIDE-版本-x64-Portable.zip解压到任意目录即用不写注册表、不留安装痕迹拷到 U 盘也能在别的电脑直接运行包内附《使用说明.txt》。适合先试用、或在受限电脑上学习本系列课程。仓颉 SDK 请前往仓颉编程语言官网下载https://cangjie-lang.cn

相关新闻

RAI 1.8.0 量化格式揭秘:Qwen2.5-7B-Instruct_rai_1.8.0_medusa_1.0_npu 如何在 NPU 上实现低精度高效推理

RAI 1.8.0 量化格式揭秘:Qwen2.5-7B-Instruct_rai_1.8.0_medusa_1.0_npu 如何在 NPU 上实现低精度高效推理

大模型基础模型Qwen 【免费下载链接】Qwen2.5-7B-Instruct_rai_1.8.0_medusa_1.0_npu 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Qwen2.5-7B-Instruct_rai_1.8.0_medusa_1.0_npu 点击查看 免费下载 📌 一句话摘要:Qwen2.5-7B-Instru…

2026/10/19 12:15:28 阅读更多 →
PHP8.2升级实测:性能提升超2倍

PHP8.2升级实测:性能提升超2倍

一、写在前面最近在折腾服务器的时候,顺手把一台老机器上的 PHP 从 7.4 升到了 8.2。说实话,升级之前心里是有点打鼓的,毕竟项目里跑着不少老代码,怕兼容性出幺蛾子。结果跑了一轮压测下来,发现性能提升比想象中明显&a…

2026/10/19 12:15:28 阅读更多 →
批量加水印还在用在线工具?30 张图 Canvas 本地铺满实测

批量加水印还在用在线工具?30 张图 Canvas 本地铺满实测

上传、等进度条、下载压缩包,这是在线加水印的标准三步。 我把这三步全砍了。图片不出浏览器,水印用 Canvas 画,导出直接落盘。 30 张图混着 800600 到 38402160 一起跑,四次实测分别是 4.57 秒、4.66 秒、4.89 秒和 4.57 秒。 …

2026/10/19 12:14:27 阅读更多 →

最新新闻

C标准库源码深度剖析:从printf到malloc的底层实现与移植指南

C标准库源码深度剖析:从printf到malloc的底层实现与移植指南

简介:这份资源是C标准库的完整源代码集合,面向希望深入理解C语言底层实现、提升系统级编程能力的开发者与学习者。它涵盖输入输出、字符串处理、内存管理、数学运算、时间日期、文件系统接口等核心模块,适合在阅读源码、优化性能或进行底层开…

2026/10/19 13:00:15 阅读更多 →
AI图像生成提示词工程:从一句话到稳定可复刻配方

AI图像生成提示词工程:从一句话到稳定可复刻配方

你有没有过这种体验:好不容易憋出一句描述,丢给生成工具,出来的图和脑子里想的完全不是一回事,换两次种子还是不对,于是觉得是模型不行,或者干脆怪自己运气差。 我也经历过这个阶段。后来把提示词从“一句…

2026/10/19 13:00:15 阅读更多 →
2026年AI Agent构建全栈应用:多Agent协作与工程化实践指南

2026年AI Agent构建全栈应用:多Agent协作与工程化实践指南

1. 为什么“AI Agent 构建全栈应用”在2026年成了绕不开的命题2026年再聊“用 AI Agent 构建全栈应用”,如果还停留在“让模型帮我补全一段函数”的层面,那基本等于白聊。我从2024年开始陆续用 Agent 跑过十几个大小项目,从内部工具到面向用户…

2026/10/19 13:00:15 阅读更多 →
AIoT端侧猫狗识别实战:从模型选型到多模态融合的工程化落地

AIoT端侧猫狗识别实战:从模型选型到多模态融合的工程化落地

1. 从一个喂食器的误触发说起:AIoT端侧识别的真实门槛去年帮一个做宠物硬件的团队看他们的智能喂食器样机,场景很简单:猫靠近就出粮,狗靠近不出粮,防止狗偷吃猫粮。听起来是个二分类问题,ImageNet上随便一个…

2026/10/19 13:00:15 阅读更多 →
AI生产力全链路:输入-认知-输出三层解耦与协议化协同

AI生产力全链路:输入-认知-输出三层解耦与协议化协同

1. “三位一体AI生态”不是营销话术,而是生产力链路的物理切分“三位一体AI生态”这个词最近在不少技术社区和产品发布会里高频出现,但很多人听完只记得个概念,回去一想——这到底跟我每天要写的周报、要调的模型、要改的PRD有什么关系&#…

2026/10/19 13:00:15 阅读更多 →
工业时序预测实战:基于CNN-BiLSTM-Attention的三模态融合模型

工业时序预测实战:基于CNN-BiLSTM-Attention的三模态融合模型

1. 三模态融合的架构设计与选型理由1.1 为什么偏偏是CNN、BiLSTM、Attention三件套工业时序预测(比如设备剩余寿命预测、关键部件温度趋势预估、整线能耗滚动预报)有一个共性痛点:数据维度高、噪声大、时间依赖长,单靠一种模型总是…

2026/10/19 12:59:13 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →