格格不入 - 软件开发
type: channel
link: https://www.jbea.cn/category/dev/
description: 摸鱼的时候来写点玩意
items: 基于C#和MailKit构建企业级邮件客户端的实战指南
items: Java 格式化输出 printf 用法
items: AxWindowsMediaPlayer (Windows Media Play)控件的常用属性、方法及事件
items: ADO.NET阶段练习与测试
items: 数据库访问技术ADO.NET
items: T-SQL编程之数据的分组查询
items: T-SQL编程之数据的模糊查询
items: T-SQL编程之数据的查询基础
items: T-SQL编程之数据的增删改操作
items: TreeView树状视图动态绑定

基于C#和MailKit构建企业级邮件客户端的实战指南
type: item
date: 2025-05-20T18:04:00+08:00
description: 一、场景价值与工具选型1.1 企业邮件系统需求自动化处理工单邮件系统监控报警通知批量发送业务报表邮件数据归档分析1.2 为什么选择MailKit？🔐 全面支持SSL/TLS加密📦 完善的MIME消息处理⚡ 真正的异步IO实现📈 活跃的开源社区支持二、快速搭建开发环境2.1 创建项目与依赖安装# 创建控制台项目 dotnet new console -n EmailClient # 添加NuGet包 dotnet add package MailKit dotnet add package MimeKit2.2 配置邮箱连接参数public class EmailConfig { // 腾讯企业邮箱示例 public const string ImapServer = "imap.exmail.qq.com"; public const int ImapPort = 993; public const string SmtpServer = "smtp.exmail.qq.com"; public const int SmtpPort = 465; // 实际项目建议使用配置文件或密钥管理服务 public const string Username = "your@company.com"; public const string Password = "your_auth_code"; }三、核心功能实现详解3.1 未读邮件处理模块public void ProcessUnreadEmails() { using var client = new ImapClient(); // 建立安全连接 client.Connect(EmailConfig.ImapServer, EmailConfig.ImapPort, SecureSocketOptions.SslOnConnect); client.Authenticate(EmailConfig.Username, EmailConfig.Password); var inbox = client.Inbox; inbox.Open(FolderAccess.ReadWrite); // 高效搜索未读邮件 var uids = inbox.Search(SearchQuery.NotSeen); foreach (var uid in uids) { var message = inbox.GetMessage(uid); ProcessMessage(message); // 标记为已读（符合企业合规要求） inbox.AddFlags(uid, MessageFlags.Seen, true); } } private void ProcessMessage(MimeMessage message) { Console.WriteLine($"\n📨 收到新邮件 [{message.Date}]"); Console.WriteLine($"主题：{message.Subject}"); Console.WriteLine($"发件人：{message.From}"); // 智能解析正文内容 var textPart = message.TextBody; var htmlPart = message.HtmlBody; Console.WriteLine($"内容预览：{textPart?.Truncate(100)}"); // 安全保存附件 SaveAttachments(message.Attachments); } /// /// 安全保存邮件附件 /// /// 附件集合 private void SaveAttachments(IEnumerable<MimeEntity> attachments) { // 创建附件存储目录 var attachmentDir = Path.Combine(Directory.GetCurrentDirectory(), "Attachments"); Directory.CreateDirectory(attachmentDir); int index = 1; foreach (var attachment in attachments) { try { string fileName; if (attachment is MessagePart rfc822) { // 处理邮件型附件（.eml） fileName = $"forward_{DateTime.Now:yyyyMMddHHmmss}_{index}.eml"; using var stream = File.Create(Path.Combine(a…

Java 格式化输出 printf 用法
type: item
date: 2024-03-06T08:58:57+08:00
description: Java 格式化输出 printf 用法符号解释使用案例%s输出字符串System.out.printf("你好,我叫:%s",myName);%d输出整数System.out.printf("你好,今年:%d岁",age);%f输出小数System.out.printf("你好,今天一共消费:%f元",money);%n输出换行 %b输出布尔类型 %S输出字符串,英文大写 import java.util.Date; /** * 使用printf输出 * 关键技术点 * 使用java.io.PrintStream的printf方法实现C风格的输出 * printf 方法的第一个参数为输出的格式,第二个参数是可变长的,表示待输出的数据对象 */ public class Demo { public static void main(String[] args) { /*** 输出字符串 ***/ // %s表示输出字符串，也就是将后面的字符串替换模式中的%s System.out.printf("%s", new Integer(1212)); // %n表示换行 System.out.printf("%s%n", "end line"); // 还可以支持多个参数 System.out.printf("%s = %s%n", "Name", "Zhangsan"); // %S将字符串以大写形式输出 System.out.printf("%S = %s%n", "Name", "Zhangsan"); // 支持多个参数时，可以在%s之间插入变量编号，1$表示第一个字符串，3$表示第3个字符串 System.out.printf("%1$s = %3$s %2$s%n", "Name", "san", "Zhang"); /*** 输出boolean类型 ***/ System.out.printf("true = %b; false = ", true); System.out.printf("%b%n", false); /*** 输出整数类型***/ Integer iObj = 342; // %d表示将整数格式化为10进制整数 System.out.printf("%d; %d; %d%n", -500, 2343L, iObj); // %o表示将整数格式化为8进制整数 System.out.printf("%o; %o; %o%n", -500, 2343L, iObj); // %x表示将整数格式化为16进制整数 System.out.printf("%x; %x; %x%n", -500, 2343L, iObj); // %X表示将整数格式化为16进制整数，并且字母变成大写形式 System.out.printf("%X; %X; %X%n", -500, 2343L, iObj); /*** 输出浮点类型***/ Double dObj = 45.6d; // %e表示以科学技术法输出浮点数 System.out.printf("%e; %e; %e%n", -756.403f, 7464.232641d, dObj); // %E表示以科学技术法输出浮点数，并且为大写形式 System.out.printf("%E; %E; %E%n", -756.403f, 7464.232641d, dObj); // %f表示以十进制格式化输出浮点数 System.out.printf("%f; %f; %f%n", -756.403f, 7464.232641d, dObj); // 还可以限制小数点后的位数 System.out.printf("%.1f; %.3f; %f%n", -756.403f, 7464.232641d, dObj); /*** 输出日期类型***/ // %t表示格式化日期时间类型，%T是时间日期的大写形式，在%t之后用特定的字母表示不同的输出格式 Date date = new Date(); long dataL = date.getTime(); // 格式化年月日 // %t之后用y表示输出日期的年份（2位数的年，如99） // %t之后用m表示输出日期的月份，%t之后用d表示输出日期的日号 System.out.printf("%1$ty-%1$tm-%1$td; %2$ty-%2$tm-%2$td%n", date, dataL); // %t之后用Y表示输出日期的年份（4位数的年）， // %t之后用B表示输出日期的月份的完整名， %t之后用b表示输出日期的月份的简称 System.out.printf("%1$tY-%1$tB-%1$td; %2$tY-%2$tb…

AxWindowsMediaPlayer (Windows Media Play)控件的常用属性、方法及事件
type: item
date: 2023-11-07T11:17:35+08:00
description: 概述AxWindowsMediaPlayer 对象是 Windows 媒体播放器 控件的根对象。本案例AxWindowsMediaPlayer控件取名: axPlay常用属性 [表-1]属性名数据类型描述或用法URLstring设置或获取媒体位置，本机或网络地址uiModestring设置或获取播放器的页面显示模式取值范围：Full, Mini, None, InvisibleplayStateWMPLib.WMPPlayState获取播放状态常见取值范围：wmppsStopped(停止)wmppsPaused(暂停)wmppsPlaying(正在播放)wmppsBuffering(正在缓冲)wmppsTransitioning(正在连接)wmppsReady(准备就绪)enableContextMenubool是否启用右键菜单fullScreenbool是否全屏显示Ctlcontrols-播放器控制属性，请查考[表-2]settings-播放器基本设置，请查考[表-3]currentMedia-播放器当前媒体，请查考[表-4]currentPlaylist-播放器当前播放列表，请查考[表-5]// 设置播放器的播放路径 axPlay.URL = @"C:\Demo\我爱的人.mp4"; // 设置播放器的页面显示模式 axPlay.uiMode = "Full"; // 获取播放器播放状态 var state = axPlay.playState; if(state == WMPLib.WMPPlayState.wmppsStopped) { // 播放器已停止播放 } // 禁用右键菜单 axPlay.enableContextMenu = false; // 开启全屏显示 axPlay.fullScreen = true;播放器基本控制属性常用方法 [表-2] [使用案例: axPlay.Ctlcontrols]方法名/属性名返回值类型描述或用法axPlay.Ctlcontrols.play()void控制播放器进行播放axPlay.Ctlcontrols.pause()void暂停axPlay.Ctlcontrols.stop()void停止axPlay.Ctlcontrols.next()void播放下一个媒体元素[需要提供播放列表]axPlay.Ctlcontrols.previous()void播放上一个媒体元素[需要提供播放列表]axPlay.Ctlcontrols.fastForward()void快进axPlay.Ctlcontrols.fastReverse()void快退axPlay.Ctlcontrols.currentPositiondouble获取或设置当前播放进度axPlay.Ctlcontrols.currentPositionStringstring获取当前播放进度,返回字符串格式。如“00:23”播放器基本控制属性常用方法 [表-3] [使用案例: axPlay.settings]方法名/属性名返回值类型描述或用法axPlay.settings.volumeint设置或获取音量，0-100axPlay.settings.autoStartbool是否自动播放axPlay.settings.mutebool是否开启静音axPlay.settings.playCountint播放次数播放器基本控制属性常用方法 [表-4] [使用案例: axPlay.currentMedia]方法名/属性名返回值类型描述或用法axPlay.currentMedia.durationdouble媒体总长度axPlay.currentMedia.durationStringstring媒体总长度，字符串格式。如“03:24”axPlay.currentMedia.getItemInfo(string bstrItemName)string获取当前媒体信息，bstrItemName参数填写字符串如下: "Title"=媒体标题"Author"=艺术家"Copyright"=版权信息"Description"=媒体内容描述"Duration"=持续时间（秒）"FileSize"=文件大小"FileType"=文件类型"sourceURL"=原始地址axPlay.currentMedia.setItemInfo(string bstrItemName, string bstrVal)void通过属性名设置媒体信息播放器基本控制属性常用方法 [表-5] [使用案例: axPlay.currentPlaylist]方法名/属性名返回值类型描述或用法axPlay.currentPlaylist.countint当前播放列表所包…

ADO.NET阶段练习与测试
type: item
date: 2023-10-27T08:36:00+08:00
description: 建立数据库新建数据库：GoodsInfo新建数据表：Category 【商品类别表】列名称数据类型是否为空说明CIDint否标识列，主键，商品类别编号CNamenvarchar(50)否商品类别名称新建数据表：Goods 【商品信息表】列名称数据类型是否为空说明GIDint否标识列，主键，商品编号GNamenvarchar(50)否商品名称CIDint否商品所属类别编号，外键Pricemoney否商品售价Brandnvarchar(20)否商品品牌名称Inventoryint否商品库存数据表建立结束后，请自行建立表与表之间的关系，并使用INSERT语句向每张表中至少添加3条测试数据。新建项目使用Visual Studio新建控制台应用程序：GoodsManagerSys，并创建数据库帮助类：DBHelper.cs，在数据库帮助类中完成实现对应方法。创建业务处理类：GoodsBusiness.cs，创建以下方法，请自行查看方法说明与注释。方法名返回值参数说明方法说明Menu()void/用于显示主菜单AddGoodsInfo()void/新增商品ShowGoodsCategory()void/显示商品分类列表ShowGoodsList()void/显示商品列表运行效果图为了让你们能够复制显示文本,项目运行效果图将以文本的形式提供----------------商品信息管理系统---------------- 1. 显示所有商品分类信息 2. 显示所有商品信息 3. 新增商品信息 4. 退出 ----------------------------------------------- 请选择操作菜单: 1 ----------------------------------------------- 商品分类编号 商品分类名称 ----------------------------------------------- 1 数码产品 2 家居用品 3 家用百货 4 休闲食品 ----------------------------------------------- 按任意键返回主菜单: x ----------------商品信息管理系统---------------- 1. 显示所有商品分类信息 2. 显示所有商品信息 3. 新增商品信息 4. 退出 ----------------------------------------------- 请选择操作菜单: 2 ----------------------------------------------- 商品编号 商品名称 品牌 售价 分类 库存 ----------------------------------------------- 1 华为Meta60 pro 华为 8999 数码产品 10 2 iPhone 15 pro 苹果 7999 数码产品 29 3 康师傅牛肉面 康师傅 5.5 休闲食品 9000 4 舒肤佳沐浴露 舒肤佳 49.9 家用百货 700 ----------------------------------------------- 按任意键返回主菜单: o ----------------商品信息管理系统---------------- 1. 显示所有商品分类信息 2. 显示所有商品信息 3. 新增商品信息 4. 退出 ----------------------------------------------- 请选择操作菜单: 3 您将要新增商品信息,请按要求依次输入 请输入商品名称: 山泉水 请输入商品品牌: 娃哈哈 请输入商品售价: 2.5 请输入商品入库库存: 200 请选择商品所属类别: ----------------------------------------------- 商品分类编号 商品分类名称 ----------------------------------------------- 1 数码产品 2 家居用品 3 家用百货 4 休闲食品 ----------------------------------------------- 请输入类别编号: 5 很抱歉,您输入的编号无效,请重新输入: 7 很抱歉,您输入的编号无效,请重新输入: 1 商品信息添加成功|失败,请按任意键返回主菜单: q ----------------商品信息管理系统---------------- 1. 显示所有商品分类信息 2. 显示所有商品信息 3. 新增商品信息 4. 退出 ----------------------------------------------- 请选择操作菜单: 4 谢谢您的使用,再见!运行与测…

数据库访问技术ADO.NET
type: item
date: 2023-10-12T17:18:00+08:00
description: 概述概述： ADO.NET是一组公开数据访问服务的类，可以对数据源进行连接，对数据进行增、删、改、查等操作。ADO.NET为创建分布式数据共享应用程序提供了一组发放的组件。特点： 与数据源断开连接后也可以使用数据ADO.NET核心组件DataSet（数据集）：独立于数据源的数据访问，DataSet是一个内存中的缓存，用于在应用程序中保存从数据库中检索的数据。它可以包含多个DataTable对象，关系和约束，可以方便地在应用程序中进行数据处理。.NET 数据提供程序[scode type="green" size="small"]1️⃣直接对数据源进行操作2️⃣连接数据源、执行命令和检索结果3️⃣实现数据操作和对数据的快速、只进只读访问[/scode].NET 数据提供程序中的4大核心对象[scode type="blue" size="small"]1️⃣Connection：用于开启程序和数据库之间的连接，它是连接数据库的关键组件，可以打开和关闭与数据库的连接。通过Connection对象，你可以指定数据库的位置、凭据、连接超时等参数。2️⃣Command：用于对数据库发出一些操作指令，它允许你执行SQL语句（例如SELECT、INSERT、UPDATE、DELETE等），并从数据库中检索数据或修改数据。Command对象也可以执行存储过程。3️⃣DataAdapter：在数据源和DataSet之间执行数据传输工作，DataAdapter是用于填充DataSet（数据集）和更新数据库的桥梁。它可以从数据库中检索数据，并将其填充到DataSet中的DataTable对象中。同样，它也可以从DataSet中获取更改，并将这些更改更新回数据库。4️⃣DataReader：DataReader是一种只进只读的数据访问方式。当你执行查询并希望逐行读取结果时，DataReader非常有用。它比DataSet更轻量级，对于大型数据集来说，性能更好，因为它不需要将整个结果集加载到内存中。[/scode]Connection连接对象语法：SqlConnection connection = new Sqlconnection(String ConnectionString);Connection对象常用属性和方法：属性🔨 / 方法📦说 明🔨 ConnectionString设置/获取应用程序连接数据库的连接字符串📦 void Open()用于打开与指定数据库的连接📦 void Close()关闭与数据库的连接使用案例演示：// 第一步: 定义链接字符串 private string constr constr = @"server=数据库服务引擎IP地址或主机名称;database=数据库名称;user=用户名;pwd=密码"; /* 数据库链接字符串拼接方式有很多种 * 例如: * Data Source=服务器名称或IP地址;Initial Catalog=数据库名;User Id=用户名;pwd=密码; * Data Source=服务器名称或IP地址;Initial Catalog=数据库名;Integrated Security=True; //Windows集成验证 */ // 第二步: 创建连接对象,此处演示案例为连接SQL Server数据库 SqlConnection connection = new Sqlconnection(constr); //在创建连接对象时,需要提供连接字符串 // 第三步: 打开或关闭连接对象 connection.Open(); //打开连接。如需关闭,请使用Close()方法[scode type="red" size="small"]⚠注意在.NET Core 框架下，不会自动添加System.Data和System.Data.SqlClient的引用，需要在菜单栏，选择"工具(T)" >"NuGet包管理器(N)";在“NuGget – 解决方案”窗口“浏览”选项卡的搜索框中输入“System.Data.SqlClient”关键字;点中搜索列表中匹配的条目，勾选项需要添加引用的项目，点击安装[/scode][scode type="green" size="small"]💬提示：在进行数据库连接或操作数据库时，请在代码中添加合理的try-catch-finally异常处理语句try{ //可能会出现异常的代码 }catch(Exception ex){ //出现异常后进行的处理代码 }finally{ //不管是否出现异常都需要执行的代码 }[/scode]Command命令对象功能:执行返回单条记录的SELECT语句，例如聚合函数SUM、AVG等执行返回具有多条记录的SELECT语句执…

T-SQL编程之数据的分组查询
type: item
date: 2023-10-09T09:24:00+08:00
description: 前言这篇文章主要是介绍数据库的基础查询相关操作，适合没有任何数据库操作基础的人员查阅。如果您有相关的数据库开发经验，那这篇文章将对您没有任何帮助。表连接分类联接查询分为内联接、外联接、交叉联接。内连接[scode type="green" size="small"]1️⃣ 最典型、最常用的连接查询2️⃣ 根据两张表中共同的列进行匹配3️⃣ 两个表存在主外键关系时，通常会使用内连接查询[/scode]演示案例表结构分析：图书信息表 [BookInfo]IdNamePriceAuthorCId1C#高级156克里斯琴•内格尔12SQL Server高级编程128美维埃拉13WinForm程序设计58王希斌14美术概论20艾苓2图书分类表 [BookCategory]CIdCategoryName1IT类2艺术类3科普类内连接语法：SELECT 列名 FROM 表名1 INNER JOIN 表名2 ON 表名1.列 = 表名2.列 --INNER可以省略，ON用来设置两个表之间的关联条件 ... WHERE 筛选条件 /* INNER JOIN 关键字后面是关联表，ON关键字后是表间联接字段的关系 */演示案例：SELECT B.Id, C.CategoryName, B.Name, B.Price, B.Author FROM BookInfo B INNER JOIN BookCategory C ON B.CId = C.CId -- 使用WHERE子句实现内连接[不推荐],下面代码执行后可以得到相同的执行结果 SELECT B.Id, C.CategoryName, B.Name, B.Price, B.Author FROM BookInfo B,BookCategory C WHERE B.CId = C.CId执行结果：IdNamePriceAuthorCategoryName1C#高级156克里斯琴•内格尔IT类2SQL Server高级编程128美维埃拉IT类3WinForm程序设计58王希斌IT类4美术概论20艾苓艺术类外连接[scode type="green" size="small"]特点：1️⃣ 外连接可以分为主表和从表2️⃣ 主表的数据会被完全显示出来3️⃣ 从表中只显示满足连接条件的数据4️⃣ 外连接结果一般会比主表和从表中数据量最小的表中的数据多分类：左外连接（LEFT JOIN）右外连接（RIGHT JOIN）完全连接（FULL JOIN）[/scode]演示案例表结构分析：用户信息表 [UserInfo]UserIdUserName1张三2李四3夏颖4李沁图书借阅记录表 [BorrowInfo]BIdUserIdBorrowDate112021-02-03212021-02-03322021-02-05432021-03-05内连接语法：SELECT 列名 FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 表名1.列 = 表名2.列 --OUTER可以省略，ON用来设置两个表之间的关联条件,LEFT可以替换为:RIGHT \ FULL ... WHERE 筛选条件演示案例：-- 统计每位用户的借书情况并显示没有借阅过图书的用户 SELECT U.UserName,B.BorrowDate,B.BId FROM UserInfo U LEFT OUTER JOIN BorrowInfo B ON B.UserId = U.UserId查询结果：UserNameBIdBorrowDate张三12021-02-03张三22021-02-03李四32021-02-05夏颖42021-03-05李沁NULLNULL[scode type="blue" size="small"]主表（左表）UserInfo中的数据逐条匹配表BorrowInfo中的数据• 匹配，返回到结果集• 无匹配，NULL值返回到结果集💬 左外联接是以左表为基础的，左表的记录将会全部表示出来，而右表只会显示符合搜索条件的记录。右表记录不足的地方均为NULL右外连接：右外连接的原理与左外连接相同右表逐条匹配记录，否则使用NULL填充完全连接：会从两个连接表中获取数据如果有对应关系，则会填上对应数据；否则，以NULL值填充[/scode]聚合函数概念：对一组值进行计算，并返回计算后的值，具有统计数据的作用函数名称说明注意SUM()返回表达式中所有值的和• 用于返回表达式中所有值的和• 只能用于数字列• 如果参与计算记录在该列上的值为空值（NULL），则此条记录在计算中将被忽略AVG()返回表达式的平均值• 用于返回表达式中所有数值的平均值• 该列值为空（NULL）的记录将被忽略MIN()返回表达式的最小值• 返回表达式中的…

T-SQL编程之数据的模糊查询
type: item
date: 2023-10-08T11:12:00+08:00
description: 前言这篇文章主要是介绍数据库的基础查询相关操作，适合没有任何数据库操作基础的人员查阅。如果您有相关的数据库开发经验，那这篇文章将对您没有任何帮助。概念模糊查询提取的数据不一定是确切的，查询者对查询条件也是模糊的、大概的、不特别明确的。本篇文章会使用：LIKE 、BETWEEN ... AND ... 、IN 三种查询方式。LIKE英文直译：相似；类似；像…一样案例分析：-- 查询出姓李且是名字是两个字的学员信息 SELECT * FROM Student WHERE Name LIKE '李_' /* 查询出来的数据有: * 李明、李阳、李芳、李伟、李霞、李婷、李峰、李梅、李雪、李霞等... */ -- 查询出姓李的学员信息(名字可以是多个字) SELECT * FROM Student WHERE Name LIKE '李%' /* 查询出来的数据有: * 李、李芳、李明霞、李春梅、李婷、李冬梅、李芳、李梅、李春霞等... */ -- 查询出名字中包含李的学员信息 SELECT * FROM Student WHERE Name LIKE '%李%' /* 查询出来的数据有: * 李、张李、李明霞、李春梅、王李婷、李冬梅、李芳、李梅、李春霞等... */LIKE在实际开发过程中使用频率极高，通常LIKE需要和统配符一同使用该运算符只用于字符串，因此仅与字符数据类型（如 char或 varchar等）联合使用通配符解释示例_一个任意字符A LIKE 'V_'，则符合条件的A如“VR”、“VC”等%任意长度的字符串(可以是0个、1个或多个)B LIKE 'SQL%'，则符合条件的A如“SQL Server”、“SQL Server高级编程”等[]括号中所指定范围内的一个字符C LIKE '900[1-2]'，则符合条件的C如“9001”或“9002”[^]不在括号中所指定范围内的任意一个字符D LIKE '900[^1-2]'，则符合条件的D如“9003”或“9007”等BETWEEN...AND...英文直译：介于…之间；在…之间案例分析：-- 查询出年龄在18岁到20岁之间的学员信息 SELECT * FROM Student WHERE Age BETWEEN 18 AND 20 -- 查询出年龄不在18岁到20岁之间的学员信息 SELECT * FROM Student WHERE Age NOT BETWEEN 18 AND 20[scode type="yellow" size="small"]⚠注意：该运算符用于查找介于两个已知值之间的一组未知值，可以是数字、文本或者日期初值要小于等于终值，如果终值小于初值，语句执行无错误，但是不会返回查询结果查找结果包含初值和终值[/scode]IN英文直译：在……里面， 在……之内案例分析：-- 查询出地址在'长沙'、'衡阳'、'深圳'和'怀化'的学员信息 SELECT * FROM Student WHERE [Address] IN ('长沙','衡阳','深圳','怀化') -- 查询出地址不在'长沙'、'衡阳'、'深圳'和'怀化'的学员信息 SELECT * FROM Student WHERE [Address] NOT IN ('长沙','衡阳','深圳','怀化')

T-SQL编程之数据的查询基础
type: item
date: 2023-09-25T11:27:00+08:00
description: 前言这篇文章主要是介绍数据库的基础查询相关操作，适合没有任何数据库操作基础的人员查阅。如果您有相关的数据库开发经验，那这篇文章将对您没有任何帮助。查询语法SELECT [TOP N [PERCENT]] <列名> FROM <表名> -- TOP N 表示取前面N条数据,PERCENT表示取前面N%的数据(百分百) [WHERE <查询条件表达式>] [GROUP BY <分组的列名> [HAVING <分组后的数据查询条件表达式>]] --HAVING表达式需要和分组一同使用 [ORDER BY <排序的列名> [ASC或DESC]] -- 默认排序为升序ASC --ORDER BY只能出现在查询语句的末尾 演示案例原始表结构查询所有列数据执行SQL语句： SELECT * FROM Student查询结果：查询部分列执行SQL语句：SELECT StudentNo,StudentName,Email,BornDate FROM Student执行结果：查询中使用别名执行SQL语句：SELECT S.StudentNo AS '学号', --使用AS关键字的形式 S.StudentName '学生姓名', --使用空格的形式 '邮箱' = S.Email, --使用等于("=")符号的形式 S.BornDate --可以使用表别名.列名的形式访问对应表的列 FROM Student S --表别名,在单表查询模式中不推荐使用,在多表连接查询中使用频率较高执行结果：SQL中的运算符算术运算符运算符说 明+加运算，求两个数或表达式相加的和。例如：SELECT 1+2，返回：3-减运算，求两个数或表达式相减的差。例如：SELECT 2-1,返回：1*乘运算，求两个数或表达式相乘的积。例如：SELECT 2*2，返回：4/除运算，求两个数或表达式相除的商。例如：SELECT 5/5，返回：1；SELECT 5.7/3，返回：1.900000%取模运算，求两个数或表达式相除的余数，例如：SELECT 5%3，返回：2演示案例：-- 为查询结果添加新列 “折扣后价格”，结合算术运算符实现图书价格8折计算 SELECT Name AS 图书名称, Price AS 价格, Author AS 作者, Price * 0.8 AS 折扣后价格 -- 实现图书价格8折计算 FROM BookInfo比较运算符运算符说 明=等于，例如：age=23>大于，例如：price>100<小于<>不等于>=大于等于<=小于等于!=不等于（非SQL-92标准 ）演示案例：SELECT Name AS 图书名称, Price AS 价格, Author AS 作者 FROM BookInfo WHERE Price < 100 -- 查询出图书价格低于100元的图书信息赋值运算符运算符说 明=把一个数或变量或表达式赋值给另一变量，如：Name='王华'逻辑运算符运算符说 明AND当且仅当两个布尔表达式都为true时，返回TRUEOR当且仅当两个布尔表达式都为false，返回FALSENOT对布尔表达式的值取反，优先级别最高IS NULL把某个值与NULL值进行比较，当表达式值为NULL时，返回TRUE演示案例：SELECT Name AS 图书名称, Price AS 价格, Author AS 作者 FROM BookInfo WHERE Name = 'C#高级' AND Author = '克里斯琴•内格尔' -- 多个查询条件查询语句中的排序使用ORDER BY子句对查询后的结果集按指定列进行排序,支持多列排序ASC升序（默认）DESC降序系统函数日期函数-用于操作日期值函数名称说明示例📌DATEADD将指定的数值添加到指定的日期部分后的日期SELECT DATEADD(dd,3,'2021-03-01')返回：以当前数据库的日期格式返回2021-03-04📌DATEDIFF两个日期之间的指定日期部分的间隔SELECT DATEDIFF(dd, '2021-03-01', '2021-03-04')返回：3📌GETDATE取得当前系统的时间和日期SELECT GETDATE()返回：2021-03-16 15:22:47.087DATENAME日期中指定日期部分的字符串形式SELECT DATENAME(dw, '2021-03-01')返回：星期一DATEPART日期中指定日期部分的整数形式SELECT DATEPART(day, '2021-03-10')返回：10DAY取得指定日期中的天的整数SELECT DAY(GETDATE())返回：今天的日期中天的整数例如：GETDATE()为2021-2-25 12:00:00.000，则DAY()…

T-SQL编程之数据的增删改操作
type: item
date: 2023-09-22T11:07:00+08:00
description: 前言这篇文章主要是介绍SQL语言以及基本的数据库的相关操作，适合没有任何数据库操作基础的人员查阅。如果您有相关的数据库开发经验，那这篇文章将对您没有任何帮助。SQL简介SQL：Structured Query Language(结构化查询语言)，是关系型数据库系统的标准语言，可以用于存取数据以及查询、更新和管理关系数据库系统。T-SQL ：Transact-SQL，是微软对SQL的扩展，具有SQL的主要特点，同时增加了变量、运算符、函数、流程控制和注释等语言元素，使得其功能更加强大。T-SQL的组成名称用途所含语法DML(Data Manipulation Language，数据操作语言)插入、修改和删除数据库中的数据INSERT、UPDATE及DELETE语句等DDL(Data Definition Language，数据定义语言)以CREATE或DROP开头的命令，例如建立数据库、数据库对象定义等CREATE TABLE、CREATE VIEW及DROP TABLE等DQL(Data Query Language，数据查询语言)对数据库中的数据进行查询SELECT语句等DCL(Data Control Language，数据控制语言)控制数据库组件的存取许可、存取权限等GRANT、REVOKE等SQL设计规范采用有意义的命名（数据库、表和字段等）类型命名方法注意事项数据库帕斯卡（Pascal Case）命名Ø 名称应有意义，建议选择产品或项目的名称命名Ø 避免使用特殊字符，如数字，空格之类Ø 避免使用缩写Ø 避免中文拼音数据表帕斯卡（Pascal Case）命名Ø 名称应有意义，建议使用能够表示表中存储内容的名字Ø 避免使用特殊字符，如数字，空格之类Ø 避免使用缩写Ø 避免中文拼音字段帕斯卡（Pascal Case）命名Ø 避免和表名重复Ø 避免使用系统关键字作为列名(例如:int)Ø 避免使用缩写或者特殊字符Ø 避免中文拼音注意字段名不与保留字、数据库系统或者常用的访问方法冲突数据表应该避免可为空的列保持不同数据表中相同意义的列名和类型一致SQL注释-- 单行注释 /* 多行注释 此处可以书写多条注释信息 */INSERT 插入语法: INSERT INTO 表名 (列名1,列名2,...) VALUES ('值1','值2',...)[scode type="blue" size="small"]⚠注意：在插入语句中，INTO 与 列名 可以省略，当省略列名时，VALUES提供值的时候，提供值的顺序与值的个数必须与表结构中的列完全一致，不能打乱顺序也不能少提供值。在插入语句中，不允许将标识列(自增列)写在列名中如需使用默认值，则需要明确使用：DEFAULT 关键字[/scode]插入多条数据语法-扩展：INSERT INTO 表名 (列名1,列名2,列名3,...) VALUES ('值1','值2','值3',...), -- 第1条记录 ('值1','值2','值3',...), -- 第2条记录 ('值1','值2','值3',...) -- 第3条记录UPDATE 修改语法：UPDATE 表名 SET 列名1 = '值1', 列名2 = '值2',... WHERE 条件1 AND 条件2 OR 条件3[scode type="blue" size="small"]⚠注意：WHERE条件语句后面可以存在多个过滤条件。“并且”关系使用 AND关键字连接；“或”关系使用 OR关键字连接判断是否为NULL，可以使用 IS NULL关键字判断如果条件较多，可以使用小括号()进行分组[/scode]DELETE 删除语法：DELETE FROM 表名 WHERE WHERE 条件1 AND 条件2 OR 条件3 [scode type="blue" size="small"]⚠注意：DELETE条件删除语句中，如果未指定WHERE条件语句，则将删除表中的所有数据删除主表记录时，如果该记录被子表所引用，则这条记录将删除失败[/scode]TRUNCATE 删除语法：TRUNCATE TABLE 表名 [scode type="blue" size="small"]⚠注意：TRUNCATE语句的删除记录时不允许携带 WHERE执行条件,只能整表数据删除TRUNCATE语句进行删除表中所有数据,标识列的计数也会从头开始TRUNCATE语句的删除速度较 DELETE语句更快TRUNCATE是数据定义语言(DDL)，在事务操作中不支持事务回滚TRUNCATE在删除表时如果存在外键引用时，则删除失败比如学生表引用了年级表，即使学生表中没有数据，只要外键关联存在，年级表就删不掉在实际开发过程中，请谨慎使用[/scode]

TreeView树状视图动态绑定
type: item
date: 2023-04-27T15:11:00+08:00
description: 数据表结构及关系创建数据库帮助类using System; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; namespace TreeViewDemo { /// /// 数据库帮助类 /// public static class DBHelper { /// /// 连接字符串 /// private static string constr = @"server=.;database=Demo;user=sa;pwd=cssl#123"; /// /// 获取读取器,使用完毕时需要关闭读取器 /// /// 需要执行的SQL语句 /// <returns>数据读取器</returns> public static SqlDataReader ExecuteReader(string sql) { // 创建数据库连接对象,并指定连接字符串 SqlConnection con = new SqlConnection(constr); // 创建命令对象 SqlCommand cmd = new SqlCommand(sql, con); try { con.Open(); return cmd.ExecuteReader(CommandBehavior.CloseConnection); } catch (Exception ex) { MessageBox.Show($"访问数据库是发生意外,错误信息:\r\r{ex.Message}", "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } return null; } } }窗体加载时,创建默认根节点/// /// 窗体加载时触发该事件 /// /// /// private void frmTreeViewDmeo_Load(object sender, EventArgs e) { BindRootNode(); //绑定根节点 tvDemo.ExpandAll(); //展开所有节点 } /// /// 绑定根节点 /// private void BindRootNode() { TreeNode tn = new TreeNode(); tn.Tag = 0; //绑定隐藏数据 tn.Text = "全部商品"; tvDemo.Nodes.Add(tn); //将创建出来的节点添加到TreeView控件中 }绑定二级节点-商品分类在 BindRootNode()方法最末尾添加如下代码:BindGoodsType(tn); //绑定商品分类,将商品分类添加到"全部商品"节点中BindGoodsType(TreeNode tn)方法定义如下:/// /// 加载商品分类 /// /// 根节点 private void BindGoodsType(TreeNode tn) { // 根节点创建后,绑定一级目录 [商品分类] string getGoodsTypeInfo = $"SELECT TID,TypeName FROM GoodsType"; SqlDataReader r = DBHelper.ExecuteReader(getGoodsTypeInfo); while (r != null && r.HasRows && r.Read()) { TreeNode typeNode = new TreeNode(); typeNode.Text = r["TypeName"].ToString(); typeNode.Tag = r["TID"]; tn.Nodes.Add(typeNode); } if (r != null) r.Close(); }加载不同分类下的不同商品信息在方法 BindGoodsType(TreeNode tn)里的 while循环中最末尾添加如下代码:// 在绑定该分类后,立马绑定当前分类下所有商品信息 BindGoodsInfo(typeNode);BindGoodsInfo(TreeNode typeNode)方法定义如下:/// /// 加载指定分类的商品信息 /// /// 商品分类节点 private void BindGoodsInfo(TreeNode typeNode) { string getGoodsTypeInfo = $"SELECT GID,GoodsName,Price FROM Goods WHERE TID = {typeNode.Tag}"; SqlDataReader r = DBHelper.ExecuteReader(get…