StudentInfo表 分页、增删改 存储过程+C# WinForm 存储过程实现分页和增删改查

核心内容:包含分页查询、新增学生、修改学生信息、删除学生4个存储过程,修正原代码潜在问题,补充详细注释,适配 C# WinForm 调用场景

适配表结构:StudentInfo(StudentId, StudentName, Score)(StudentId 为自增主键)

一、分页查询存储过程(usp_test3)

实现带条件筛选的分页查询,返回指定页数据,通过输出参数返回总页数,适配 VS 端分页逻辑调用。

复制代码
-- 1. 判断分页存储过程是否存在,存在则删除
if exists(select * from sysobjects where name ='usp_test3')
 drop procedure usp_test3;
go

-- 2. 创建分页存储过程
-- 参数说明:
-- @pagesize:输入参数,每页显示记录条数(由VS传递)
-- @currentpage:输入参数,当前页码(由VS传递)
-- @where:输入参数,筛选条件(带and前缀,如:and StudentName like '%张%')
-- @totalPage:输出参数,返回筛选后的总页数(供VS端分页按钮使用)
create procedure usp_test3
  @pagesize int,
  @currentpage int,
  @where varchar(max),
  @totalPage int output
as
begin
    -- 关闭计数消息返回,提升执行效率,避免返回无关的受影响行数
    SET NOCOUNT ON;

    -- 定义变量
    declare @sql1 nvarchar(max);  -- 存储分页查询的动态SQL语句
    declare @sql2 nvarchar(max);  -- 存储统计总记录数的动态SQL语句
    declare @total int;           -- 存储筛选后的总记录数
    declare @offset int;          -- 存储分页时需要跳过的记录数

    -- 计算跳过的记录数:分页核心公式(当前页-1)*每页条数
    Set @offset = (@currentpage - 1) * @pagesize;

    -- 初始化分页查询SQL(N前缀:识别为Unicode编码,避免中文乱码)
    set @sql1 = N'select * from StudentInfo where 1=1 ';

    -- 初始化统计总记录数的SQL(通过@count变量接收统计结果)
    set @sql2 = N'select @count = count(*) from StudentInfo where 1=1 ';

    -- 拼接筛选条件:若筛选条件非空(去除前后空格后长度不为0),则拼接至两个SQL后
    if(len(trim(@where)) <> 0)
    begin
        set @sql1 += @where;  -- 拼接分页查询的筛选条件
        set @sql2 += @where;  -- 拼接统计总记录数的筛选条件
    end

    -- 完善分页查询SQL:添加排序+OFFSET-FETCH分页条件
    -- 注意:OFFSET-FETCH必须配合ORDER BY使用,否则会报错
    set @sql1 += N' order by Score offset ' + CAST(@offset as nvarchar)
              + N' rows fetch next ' + CAST(@pagesize as nvarchar) + N' rows only';

    -- 执行分页查询SQL,返回当前页数据
    exec(@sql1);

    -- 执行统计总记录数的SQL,通过sp_executesql传递输出参数,获取总记录数
    -- 参数说明:@sql2(执行的SQL)、N'@count int output'(参数定义)、@total output(接收输出值)
    exec sp_executesql @sql2, N'@count int output', @total output;

    -- 计算总页数:总页数=总记录数/每页条数,若有余数则加1
    if(@total % @pagesize = 0)
        set @totalPage = @total / @pagesize;  -- 无余数,总页数为商
    else 
        set @totalPage = @total / @pagesize + 1;  -- 有余数,总页数为商+1

    -- 开启计数消息返回,恢复默认设置
    SET NOCOUNT OFF;
end
go

-- 3. 验证分页存储过程
declare @f1 int;  -- 定义变量,接收总页数(输出参数)
-- 调用存储过程:每页3条,查询第2页,无筛选条件
exec usp_test3 3, 2, '', @f1 output;
print '总页数:' + CAST(@f1 as nvarchar);  -- 打印总页数
print '------------------------';

-- 带筛选条件的验证示例(查询姓名含"张"的记录,每页3条,查询第1页)
-- declare @f2 nvarchar(max);
-- set @f2 = ' and StudentName like ''%张%'' ';  -- 注意:单引号需转义(两个单引号表示一个)
-- exec usp_test3 3, 1, @f2, @f1 output;
-- print '筛选后总页数:' + CAST(@f1 as nvarchar);

二、新增学生信息存储过程(p_stundentInfo_add)

实现学生信息的新增功能,接收学生姓名和成绩,插入到 StudentInfo 表中。

复制代码
-- 1. 判断新增存储过程是否存在,存在则删除
if exists(select * from sysobjects where name ='p_stundentInfo_add')
 drop procedure p_stundentInfo_add;
go

-- 2. 创建新增存储过程
-- 参数说明:
-- @studentName:输入参数,学生姓名
-- @score:输入参数,学生成绩
create procedure p_stundentInfo_add
  @studentName varchar(10),
  @score int
as
begin
    SET NOCOUNT ON;  -- 关闭计数消息返回
    -- 插入数据到StudentInfo表(StudentId为自增主键,无需手动赋值)
    insert into StudentInfo(StudentName, Score) values(@studentName, @score);
    SET NOCOUNT OFF;
end
go

-- 3. 验证新增存储过程
exec p_stundentInfo_add 'zs是是是', 100;  -- 调用存储过程,新增一条学生记录
select * from StudentInfo;  -- 查询表,验证新增结果

三、修改学生信息存储过程(p_studentinfo_update)

根据学生ID修改学生姓名和成绩,实现学生信息的编辑功能。

复制代码
-- 1. 判断修改存储过程是否存在,存在则删除
IF EXISTS(SELECT * FROM sys.procedures WHERE name='p_studentinfo_update')
DROP PROC p_studentinfo_update;
GO

-- 2. 创建修改存储过程
-- 参数说明:
-- @StudentId:输入参数,学生ID(修改依据,主键)
-- @StudentName:输入参数,修改后的学生姓名
-- @Score:输入参数,修改后的学生成绩
CREATE PROC p_studentinfo_update
	@StudentId int,
	@StudentName varchar(50),
	@Score int
AS
BEGIN
	SET NOCOUNT ON;  -- 关闭计数消息返回
	-- 根据学生ID更新姓名和成绩
	UPDATE StudentInfo 
	SET StudentName = @StudentName, Score = @Score 
	WHERE StudentId = @StudentId;
	SET NOCOUNT OFF;
END
GO

-- 3. 验证修改存储过程
exec p_studentinfo_update 1002, 'pis1', 10;  -- 调用存储过程,修改StudentId=1002的学生信息
select * from StudentInfo;  -- 查询表,验证修改结果

四、删除学生信息存储过程(p_studentinfo_delete)

根据学生ID删除对应的学生记录,实现学生信息的删除功能。

复制代码
-- 1. 判断删除存储过程是否存在,存在则删除
IF EXISTS(SELECT * FROM sys.procedures WHERE name='p_studentinfo_delete')
DROP PROC p_studentinfo_delete;
GO

-- 2. 创建删除存储过程
-- 参数说明:
-- @StudentId:输入参数,学生ID(删除依据,主键)
CREATE PROC p_studentinfo_delete
	@StudentId int
AS
BEGIN
	SET NOCOUNT ON;  -- 关闭计数消息返回
	-- 根据学生ID删除记录
	DELETE FROM StudentInfo WHERE StudentId = @StudentId;
	SET NOCOUNT OFF;
END
GO

-- 3. 验证删除存储过程
exec p_studentinfo_delete 1002;  -- 调用存储过程,删除StudentId=1002的学生记录
select * from StudentInfo;  -- 查询表,验证删除结果

核心优化与注意事项(必背)

1. 关键优化点

  • 添加 SET NOCOUNT ON/OFF:关闭/开启计数消息返回,提升存储过程执行效率,避免返回无关的受影响行数。

  • 补充参数说明:为每个存储过程的参数添加注释,明确参数用途、类型,适配复习和开发调用。

  • 规范验证示例:补充带筛选条件的分页调用示例,注释转义字符的使用(单引号转义),避免语法错误。

  • 统一判断方式:兼容 sysobjectssys.procedures 两种判断存储过程存在的方式,适配不同SQL Server版本。

2. 易错踩坑点

  • 分页存储过程中,动态SQL拼接时遗漏N前缀,导致中文筛选条件乱码;未添加ORDER BY子句,导致OFFSET-FETCH语法报错。

  • 筛选条件拼接时,未带and前缀(如直接写 StudentName like '%张%'),导致拼接后SQL变为 where 1=1StudentName like '%张%',出现语法错误。

  • 新增存储过程中,若StudentName字段长度不足,插入过长姓名会报错(需根据实际表结构调整参数长度)。

  • 修改、删除存储过程中,未传入StudentId或传入不存在的StudentId,会导致修改/删除无效果(无报错,需添加判断优化)。

  • 动态SQL执行时,使用exec而非sp_executesql,导致无法传递输出参数,无法获取总记录数;同时存在SQL注入风险。

3. VS端调用注意事项(适配C#)

  • 调用分页存储过程时,输出参数需指定参数方向为 ParameterDirection.Output,获取总页数后计算分页按钮状态。

  • 调用增删改存储过程时,确保传入的参数类型与存储过程定义一致(如StudentId为int,StudentName为字符串)。

  • 传递筛选条件时,需拼接and前缀,特殊字符(如单引号)需转义,避免SQL语法错误和SQL注入。

  • 调用完成后,刷新DataGridView数据,同步展示增删改后的结果。

C# WinForm 存储过程实现分页和增删改查

优化说明:补充异常处理、规范变量命名、增加输入验证、优化代码注释,解决原代码中潜在的空值、类型转换异常问题,适配实际开发场景。

复制代码
using Microsoft.ApplicationBlocks.Data.Ch;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;

namespace 使用存储过程实现分页和增删改查
{
    public partial class Form1 : Form
    {
        // 数据库连接字符串(建议放到配置文件中,此处为演示)
        private readonly string _connString = "server=.,1344;database=BankSystem;uid=sa;pwd=123456";
        
        // 分页相关变量(规范命名,增加可读性)
        private int _currentPage = 1;   // 当前页码
        private int _pageSize = 3;      // 每页显示条数
        private int _totalPage = 0;     // 总页数

        public Form1()
        {
            InitializeComponent();
            // 初始化分页下拉框,默认选中第一项(3条/页)
            cbbPageSize.SelectedIndex = 0;
        }

        /// <summary>
        /// 窗体加载事件:首次绑定数据表格
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            BindGridView();
        }

        /// <summary>
        /// 核心方法:绑定数据表格(分页查询+筛选)
        /// </summary>
        public void BindGridView()
        {
            try
            {
                // 拼接筛选条件(带and前缀,适配存储过程的where拼接逻辑)
                string whereCondition = string.Empty;
                // 姓名筛选:非空则拼接模糊查询条件
                if (!string.IsNullOrWhiteSpace(txtStudentName.Text))
                {
                    whereCondition += $" and StudentName like '%{txtStudentName.Text.Trim()}%'";
                }
                // 最低分筛选:大于0则拼接范围条件
                if (nudScoreStart.Value > 0)
                {
                    whereCondition += $" and Score >= {nudScoreStart.Value}";
                }
                // 最高分筛选:大于0则拼接范围条件
                if (nudScoreEnd.Value > 0)
                {
                    whereCondition += $" and Score <= {nudScoreEnd.Value}";
                }

                // 定义存储过程参数(输入+输出)
                SqlParameter[] parameters = new SqlParameter[]
                {
                    new SqlParameter("@currentpage", SqlDbType.Int) { Value = _currentPage },
                    new SqlParameter("@pagesize", SqlDbType.Int) { Value = _pageSize },
                    new SqlParameter("@where", SqlDbType.VarChar) { Value = whereCondition },
                    new SqlParameter("@totalPage", SqlDbType.Int) { Direction = ParameterDirection.Output } // 输出参数:总页数
                };

                // 调用分页存储过程,获取数据集
                DataSet dataSet = SqlHelper.ExecuteDataset(
                    _connString, 
                    CommandType.StoredProcedure, 
                    "usp_test3", 
                    parameters
                );

                // 获取输出参数(总页数),处理空值异常
                _totalPage = parameters[3].Value != DBNull.Value 
                    ? int.Parse(parameters[3].Value.ToString()) 
                    : 0;

                // 绑定数据到DataGridView,处理空表情况
                dataGridView1.DataSource = dataSet.Tables[0];
                // 更新分页显示标签
                lblPageAndTotalPage.Text = $"当前页:{_currentPage} / 总页数:{_totalPage}";

                // 禁用/启用分页按钮(优化用户体验)
                btnFirst.Enabled = _currentPage > 1;
                btnPrev.Enabled = _currentPage > 1;
                btnNext.Enabled = _currentPage < _totalPage;
                btnLast.Enabled = _currentPage < _totalPage;
            }
            catch (Exception ex)
            {
                // 捕获异常并提示,避免程序崩溃
                MessageBox.Show($"数据绑定失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 分页条数下拉框选择事件:修改每页显示条数,重置为第一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbbPageSize_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                // 转换下拉框选中值,更新每页显示条数
                _pageSize = int.Parse(cbbPageSize.SelectedItem.ToString());
                _currentPage = 1; // 切换每页条数后,重置为第一页
                BindGridView();   // 重新绑定数据
            }
            catch (Exception ex)
            {
                MessageBox.Show($"分页条数设置失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 搜索按钮点击事件:根据筛选条件查询,重置为第一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSearch_Click(object sender, EventArgs e)
        {
            // 重置当前页为第一页,重新绑定数据
            _currentPage = 1;
            BindGridView();
        }

        /// <summary>
        /// 新增按钮点击事件:调用新增存储过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            try
            {
                // 输入验证:姓名和成绩不能为空
                string studentName = textBox1.Text.Trim();
                if (string.IsNullOrEmpty(studentName))
                {
                    MessageBox.Show("请输入学生姓名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    textBox1.Focus(); // 聚焦到姓名输入框
                    return;
                }

                if (string.IsNullOrWhiteSpace(textBox2.Text))
                {
                    MessageBox.Show("请输入学生成绩!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    textBox2.Focus(); // 聚焦到成绩输入框
                    return;
                }

                // 成绩类型转换,处理转换异常
                if (!int.TryParse(textBox2.Text, out int score))
                {
                    MessageBox.Show("成绩必须是整数!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    textBox2.Focus();
                    return;
                }

                // 定义新增存储过程参数
                SqlParameter[] parameters = new SqlParameter[]
                {
                    new SqlParameter("@studentName", SqlDbType.VarChar) { Value = studentName },
                    new SqlParameter("@score", SqlDbType.Int) { Value = score }
                };

                // 调用新增存储过程,获取受影响行数
                int affectedRows = SqlHelper.ExecuteNonQuery(
                    _connString, 
                    CommandType.StoredProcedure, 
                    "p_stundentInfo_add", 
                    parameters
                );

                // 判断新增是否成功
                if (affectedRows > 0)
                {
                    MessageBox.Show("新增学生信息成功!", "成功提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // 清空输入框,提升用户体验
                    textBox1.Clear();
                    textBox2.Clear();
                    // 重新绑定数据,刷新表格
                    BindGridView();
                }
                else
                {
                    MessageBox.Show("新增学生信息失败,请检查参数!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"新增失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 编辑按钮点击事件:调用修改存储过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEdit_Click(object sender, EventArgs e)
        {
            try
            {
                // 验证是否选中数据行
                if (dataGridView1.CurrentRow == null || dataGridView1.CurrentRow.Index< 0)
                {
                    MessageBox.Show("请先选中要编辑的学生信息行!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                // 获取选中行的主键(StudentId),处理空值异常
                if (dataGridView1.CurrentRow.Cells["StudentId"].Value == DBNull.Value)
                {
                    MessageBox.Show("选中行的学生ID无效!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                int studentId = Convert.ToInt32(dataGridView1.CurrentRow.Cells["StudentId"].Value);

                // 输入验证
                string studentName = textBox1.Text.Trim();
                if (string.IsNullOrEmpty(studentName))
                {
                    MessageBox.Show("请输入学生姓名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    textBox1.Focus();
                    return;
                }

                if (!int.TryParse(textBox2.Text, out int score))
                {
                    MessageBox.Show("成绩必须是整数!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    textBox2.Focus();
                    return;
                }

                // 定义修改存储过程参数
                SqlParameter[] parameters = new SqlParameter[]
                {
                    new SqlParameter("@StudentId", SqlDbType.Int) { Value = studentId },
                    new SqlParameter("@StudentName", SqlDbType.VarChar, 50) { Value = studentName },
                    new SqlParameter("@Score", SqlDbType.Int) { Value = score }
                };

                // 调用修改存储过程
                SqlHelper.ExecuteNonQuery(
                    _connString, 
                    CommandType.StoredProcedure, 
                    "p_studentinfo_update", 
                    parameters
                );

                MessageBox.Show("修改学生信息成功!", "成功提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                // 清空输入框
                textBox1.Clear();
                textBox2.Clear();
                // 重新绑定数据
                BindGridView();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"修改失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 删除按钮点击事件:调用删除存储过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                // 验证是否选中数据行
                if (dataGridView1.CurrentRow == null || dataGridView1.CurrentRow.Index < 0)
                {
                    MessageBox.Show("请先选中要删除的学生信息行!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                // 获取选中行的主键(StudentId)
                if (dataGridView1.CurrentRow.Cells["StudentId"].Value == DBNull.Value)
                {
                    MessageBox.Show("选中行的学生ID无效!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                int studentId = Convert.ToInt32(dataGridView1.CurrentRow.Cells["StudentId"].Value);

                // 确认删除(防止误操作)
                DialogResult result = MessageBox.Show(
                    $"确定要删除ID为{studentId}的学生信息吗?", 
                    "确认删除", 
                    MessageBoxButtons.YesNo, 
                    MessageBoxIcon.Question
                );
                if (result != DialogResult.Yes)
                {
                    return; // 用户取消删除,直接返回
                }

                // 定义删除存储过程参数
                SqlParameter[] parameters = new SqlParameter[]
                {
                    new SqlParameter("@StudentId", SqlDbType.Int) { Value = studentId }
                };

                // 调用删除存储过程
                SqlHelper.ExecuteNonQuery(
                    _connString, 
                    CommandType.StoredProcedure, 
                    "p_studentinfo_delete", 
                    parameters
                );

                MessageBox.Show("删除学生信息成功!", "成功提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

                // 处理分页:删除后如果当前页是最后一页且无数据,页码减1
                if (_currentPage > _totalPage)
                {
                    _currentPage = _totalPage > 0 ? _totalPage : 1;
                }
                // 重新绑定数据
                BindGridView();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"删除失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 首页按钮点击事件:跳转到第一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFirst_Click(object sender, EventArgs e)
        {
            _currentPage = 1;
            BindGridView();
        }

        /// <summary>
        /// 上一页按钮点击事件:跳转到上一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrev_Click(object sender, EventArgs e)
        {
            if (_currentPage > 1)
            {
                _currentPage--;
                BindGridView();
            }
        }

        /// <summary>
        /// 下一页按钮点击事件:跳转到下一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNext_Click(object sender, EventArgs e)
        {
            if (_currentPage< _totalPage)
            {
                _currentPage++;
                BindGridView();
            }
        }

        /// <summary>
        /// 末页按钮点击事件:跳转到最后一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLast_Click(object sender, EventArgs e)
        {
            _currentPage = _totalPage;
            BindGridView();
        }

        /// <summary>
        /// 跳转按钮点击事件:跳转到指定页码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGo_Click(object sender, EventArgs e)
        {
            try
            {
                // 获取指定页码,验证有效性
                int targetPage = int.Parse(nudPage.Text);
                if (targetPage < 1 || targetPage > _totalPage)
                {
                    MessageBox.Show($"请输入1到{_totalPage}之间的页码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                _currentPage = targetPage;
                BindGridView();
            }
            catch (FormatException)
            {
                MessageBox.Show("页码必须是整数!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"页码跳转失败:{ex.Message}", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

核心优化点说明

  • 异常处理:所有数据库操作、类型转换操作都添加 try-catch 捕获异常,避免程序崩溃,同时给出友好的错误提示。

  • 输入验证:新增、编辑时验证姓名和成绩的输入有效性,处理空值、非整数等异常情况,提升用户体验。

  • 变量规范:优化变量命名(如 _currentPage、_pageSize),增加可读性,符合 C# 命名规范。

  • 分页优化:根据当前页码禁用/启用分页按钮,避免无效点击;处理删除后页码越界问题。

  • 空值处理:处理数据库返回的 DBNull 值、DataGridView 单元格空值,避免类型转换异常。

  • 用户体验优化:操作成功后清空输入框、聚焦到对应输入框,给出明确的成功/失败提示。

适配注意事项

  • 确保项目中已引用 Microsoft.ApplicationBlocks.Data.Ch 程序集(SqlHelper 所在程序集)。

  • 检查数据库连接字符串中的服务器地址、端口、账号密码,确保与实际数据库环境一致。

  • 确保数据库中已创建对应的4个存储过程(分页、新增、修改、删除),存储过程名称与代码中一致。

  • DataGridView 中需包含 StudentId 列(主键列),否则编辑、删除功能会报错。

相关推荐
影寂ldy1 小时前
WinForm 数据库【新增+编辑】完整功能(参数化查询+配置文件+防报错全套)
数据库
迷枫7122 小时前
达梦数据库 Hint 使用与 Hint 注入实战
数据库
Gauss松鼠会3 小时前
【GaussDB】GaussDB锁阻塞源头查询
java·开发语言·前端·数据库·算法·gaussdb·经验总结
2601_965798473 小时前
How to Build a Custom Artisan Store on WordPress: Crafti Theme Review
linux·服务器·数据库
霸道流氓气质3 小时前
Spring 事务传播机制与 REQUIRES_NEW
java·数据库·spring
YOU OU4 小时前
Redis分布式锁
数据库·redis·分布式
小草儿7994 小时前
GBase 8s CLOB → VARCHAR(32739) 数据迁移方案文档
数据库
秋田君4 小时前
QT_QColorDialog颜色对话框
java·数据库·qt
涛声依旧393164 小时前
运维项目:InnoAI SQL 助手
运维·数据库·sql