一、sql记录
1、sql常用函数记录
--mysql用表标识列删除重复项
--如果你想基于某列(或几列)的值来决定保留哪一行(比如总是保留ID最小的那一行),可以这样做:
DELETE t1 FROM your_table t1
JOIN (
SELECT MIN(id) as min_id, column_with_duplicates
FROM your_table
GROUP BY column_with_duplicates
HAVING COUNT(*) > 1
) t2 ON t1.column_with_duplicates = t2.column_with_duplicates AND t1.id <> t2.min_id;
--sqlserver用表标识列删除重复项
--对于支持窗口函数的数据库系统(如SQL Server、PostgreSQL、Oracle等)
--可以使用 ROW_NUMBER() 分配每个重复记录的行号,然后删除行号大于1的记录。
WITH CTE AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY column_with_duplicates ORDER BY id) as rn
FROM your_table
)
SELECT * FROM CTE WHERE rn = 1--配合公共表达式执行
DELETE FROM CTE WHERE rn > 1;--配合公共表达式执行
-- 格式化时间
format(CONVERT ( datetime, BIDDING_TIME, 120 ),'yyyy-MM-dd HH:mm:ss')
-- 获取当前系统时间并格式转换 '2024-03-06 09:20:04'
CONVERT ( VARCHAR ( 19 ), GETDATE( ), 120 )
-- 时间转换 '11 12 2022 7:08PM' -> ''2024-03-06 09:20:04''
CONVERT(varchar(19), TRY_CONVERT(datetime, 字段名, 100), 120)
-- 时间转换 去除毫秒
CONVERT(VARCHAR(19), 字段名, 120)
-- cast显式转换数据类型将guid转换成字符串
'JBWC' + CAST ( newid( ) AS VARCHAR ( 50 ) ) AS NOTICE_NO,
-- case条件逻辑控制结构 翻译字段不同的结果
CASE case_value
WHEN when_value THEN statement_list
ELSE statement_list
END as 别名
-- 截取字符段长度
SUBSTRING(截取的字段, 开始索引(从1开始), length)
-- replace替换字符串中的某一子串的
REPLACE(str, search_string, replacement_string)
2、sql备份表
在SQL中,如果你想从一个表(比如原表
)创建一个内容完全一样的新表(比如原表_copy
)
- 在SQL Server、PostgreSQL等数据库,可以使用
SELECT INTO
语句。以下是具体的SQL命令:
SELECT * INTO dawd_copy FROM dawd;
- 在MySQL中则需要采用
CREATE TABLE AS SELECT
的方式:
CREATE TABLE dawd_copy AS SELECT * FROM dawd;
3、sql批量插入数据
从Base_Advice_PrefixCode表里面查出字段然后批量插入到Sys_QuartzOptions这里面
INSERT INTO Sys_QuartzOptions(Id,TaskName,GroupName,CronExpression,Method,ApiUrl,Status,TimeOut)
SELECT newid(),Business_Type+ '-' + Table_Name,SUBSTRING(Business_Type, 1, 4),'0 0/1 * * * ?','post'
,'http://localhost:9991/api/Sys_PostDataLog/SendNqiData?tableName=' + Table_Encoding,'1','180'
FROM Base_Advice_PrefixCode
4、sql–NOT EXISTS
- 一般用于自查
not exists(select 1 from Base_Product where Base_Product.ProductCode=v_RD_PRODUCT_INFO.PRODUCT_CODE)
NOT EXISTS
是 SQL 中的一个条件表达式,主要用于在子查询中执行一个谓词测试,以判断是否存在满足特定条件的行。它常常用于在主查询中排除与子查询结果相关的记录。
在 SQL 查询中,NOT EXISTS
结构的一般语法是这样的:
SELECT ...
FROM table1
WHERE NOT EXISTS (
SELECT 1
FROM table2
WHERE condition
)
- 主查询(外部查询):
table1
中的记录是我们关注的目标集合。 - 子查询(内部查询):
table2
和其中的condition
定义了一个子集,用于检查是否存在符合条件的行。
select 1
的意思是选取一个常量值1,这里并不是指具体的某个列,而是用来构造一个布尔表达式。
NOT EXISTS
的工作原理是,对于主查询中的每一行,它都会去检查子查询是否存在满足condition
的记录。如果有哪怕一行满足条件,EXISTS
就会返回TRUE
,反之则返回FALSE
。加上NOT
后,如果子查询没有找到匹配的记录,则NOT EXISTS
返回TRUE
,主查询中对应的那行记录就会被保留下来。
举个例子:
SELECT *
FROM Orders o
WHERE NOT EXISTS (
SELECT 1
FROM OrderDetails od
WHERE od.OrderID = o.OrderID AND od.ProductID = 100
)
这个查询会返回所有在 Orders
表中但不在 OrderDetails
表中有产品ID为100的相关订单记录。
总结一下,NOT EXISTS
关键字主要用于从主查询结果集中过滤掉那些在相关子查询中能找到匹配记录的行。
5、sql-----case-when-else-end
SELECT DISTINCT
bar.ProcessCode AS 生产工序号,
pt.PLAN_CODE AS 计划单号,
bar.ProcessName AS 工序名称,
CASE
--WHEN RIGHT(PLAN_CODE, CHARINDEX('-', REVERSE(PLAN_CODE)) - 1) = '001' THEN 'PCB板工序'
--反转计划单号找到最后一个'-'后面字符的字符长度 右边开始截取最后一个‘-’后面的字符
WHEN RIGHT(PLAN_CODE, CHARINDEX('-', REVERSE(PLAN_CODE)) - 1) = '002' THEN '整表生产工序'
ELSE '整表生产工序'
END AS ProcessTypeName,
pt.FINISH_TIME,
CONVERT ( VARCHAR ( 19 ), GETDATE( ), 120 ) AS WRITE_DATE,
'N' AS HANDLE_FLAG,
'SCGX' + CAST ( newid( ) AS VARCHAR ( 50 ) ) AS NOTICE_NO,
'00444' AS ENTERPRISE_CODE
FROM
[QHNQI].dbo.PT_PRODUCTION_PLAN pt-- 生产计划记录
JOIN
[QHNQI].dbo.Base_ProcessLine bp ON -- 工艺路线
(
-- 根据你的逻辑调整这里的条件
CASE
--WHEN RIGHT(pt.PLAN_CODE, CHARINDEX('-', REVERSE(pt.PLAN_CODE)) - 1) = '001' THEN 'PCB板工序'
WHEN RIGHT(pt.PLAN_CODE, CHARINDEX('-', REVERSE(pt.PLAN_CODE)) - 1) = '002' THEN '整表生产工序'
ELSE '整表生产工序'
END = bp.ProcessLineName -- 生产计划对应的工艺名称
)
-- 工序列表
join [QHNQI].dbo.Base_ProcessLineList pll ON pll.ProcessLine_Id = bp.ProcessLine_Id --工艺路线对应的工序明细
-- 生产工序
JOIN [QHNQI].dbo.Base_Process bar ON bar.Process_Id = pll.Process_Id --工序明细对应的生产工序
WHERE
PLAN_CODE LIKE 'GW%' --生产计划的国网工单GW%
GROUP BY
bar.ProcessCode,
pt.PLAN_CODE,
bar.ProcessName,
pt.FINISH_TIME
6、sql-----自查新增记录防止重复----not Exists条件–也可用自连接
not exists(select 1 from 原表 where 原表.MAKE_PLAN_NO=来源表.MAKE_PLAN_NO)
7、sql—自连接
自连接查询是一种特殊的SQL查询方式,它在一个表自身之间建立连接,通常用于比较同一表中的不同行。
这种查询常用于层次结构数据
、父子关系数据
或任何其他需要基于表中自身的关联进行对比的情况。
以下是一个自连接查询的例子,假设我们有一个员工表Employees
,其中包含EmployeeID
, ManagerID
和EmployeeName
字段。ManagerID
字段存储每个员工的上级经理的EmployeeID
。现在,如果我们想要查询每个员工及其对应的经理的姓名,就可以使用自连接:
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
ManagerID INT,
EmployeeName VARCHAR(100)
);
INSERT INTO Employees VALUES (1, NULL, 'Boss');
INSERT INTO Employees VALUES (2, 1, 'Manager A');
INSERT INTO Employees VALUES (3, 1, 'Manager B');
INSERT INTO Employees VALUES (4, 2, 'Employee A');
INSERT INTO Employees VALUES (5, 2, 'Employee B');
INSERT INTO Employees VALUES (6, 3, 'Employee C');
-- 自连接查询
SELECT e.EmployeeName AS Employee, m.EmployeeName AS Manager
FROM Employees e
LEFT JOIN Employees m ON e.ManagerID = m.EmployeeID;
在这个例子中,我们创建了一个Employees
表,并插入了一些示例数据。然后,通过自连接,我们将员工表与自身连接起来,依据ManagerID
和EmployeeID
的匹配关系,找到了每个员工对应的经理姓名。
二、扩展记录
1)service.cs扩展 表/明细表(CRUD导入导出)前后做一些操作 数据(CRUD导入导出)前后的处理参数或数据
写在Partial部分类里面
具体文档链接点击链接:
新版:后台基础代码扩展实现链接
旧版:后台基础代码扩展实现链接
2.编辑
- 编辑时数据库表的字段前校验表请求的字段原有表中存不存在
public override WebResponseContent Update(SaveModel saveModel)
{
//编辑方法保存数据库前处理
UpdateOnExecuting = (Demo_Catalog catalog, object addList, object updateList, List<object> delKeys) =>
{
//如果数据库的分类编号与前端请求的分类编号相同
//并且该记录的主键id和请求的不同说明已存在
//这边也可以用写原生sql解决
repository.DapperContext.ExecuteScalar
("select * from .....")
if (repository.Exists(x => x.CatalogCode == catalog.CatalogCode && x.CatalogId != catalog.CatalogId))
{
return webResponse.Error(CatalogCode + "分类编号已存在");
}
return webResponse.OK();
};
return base.Update(saveModel);
}
3.新建
- 新建时数据库表的字段前校验表请求的字段原有表中存不存在
public override WebResponseContent Add(SaveModel saveDataModel)
{
// 在保存数据库前的操作,所有数据都验证通过了,这一步执行完就执行数据库保存
AddOnExecuting = (Demo_Catalog catalog, object list) =>
{
if (repository.Exists(x => x.CatalogCode == catalog.CatalogCode))
{
return webResponse.Error("分类编号已存在");
}
return webResponse.OK();
};
return base.Add(saveDataModel);
}
4.查询
- 设置前台提交的原生的查询条件
- 设置手写的sql语句
- 通过UserContext获取当前的用户的信息–做一些查询的权限(查询当前用户对应的数据)
public override PageGridData<Demo_Catalog> GetPageData(PageDataOptions options)
{
//此处是从前台提交的原生的查询条件,这里可以自己过滤
QueryRelativeList = (List<SearchParameters> parameters) =>
{
};
//前端代码
// searchBefore(param) {
// //界面查询前,可以给param.wheres添加查询参数
// //返回false,则不会执行查询
// 前端查询前添加的值(对象也可以 后端用getObject就行) param.value = 1;
// return true;
// },
//后端代码
//获取前端查询前添加的值
if (options.Value.GetInt()==1)
{
Console.WriteLine("1");
}
//2020.08.15
//设置原生查询的sql语句,这里必须返回select * 表所有字段
//(先内部过滤数据,内部调用EF方法FromSqlRaw,自己写的sql注意sql注入的问题),不会影响界面上提交的查询
//查询当前时间的数据
string date = DateTime.Now.AddHours(-10).ToString("yyyy-MM-dd");
QuerySql = $@"select * from Demo_Catalog where createdate>'{date}'";
repository.DapperContext.ex
PageGridData<Demo_Catalog> gridData = new PageGridData<Demo_Catalog>()
{
rows=new List<Demo_Catalog>() { },
total=100
};
//查询当前用户对应的数据
QueryRelativeExpression = (IQueryable<Demo_Catalog> queryable) =>
{
queryable = queryable.Where(x => x.CreateID == UserContext.Current.UserId);
return queryable;
};
return base.GetPageData(options);
}
5.导出
- 设置最大导出的数量
- 指定导出的字段
- 过滤不导出的字段
public override WebResponseContent Export(PageDataOptions pageData)
{
//设置最大导出的数量
Limit = 100000;
//指定导出的字段(2020.05.07)
ExportColumns = x => new { x.CatalogCode, x.CatalogName };
//查询要导出的数据后,在生成excel文件前处理
//list导出的实体,ignore过滤不导出的字段
ExportOnExecuting = (List<Demo_Catalog> list, List<string> ignore) =>
{
list.ForEach(item =>
{
item.CatalogCode = "11";//所有分类编号全是11
});
ignore.Add("Remark");//忽略Remark字段
return webResponse.OK();
};
return base.Export(pageData);
}
6.导入
/// <summary>
/// 导入
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
public override WebResponseContent Import(List<IFormFile> files)
{
//(2020.05.07)
//设置导入的字段(如果指定了上面导出模板的字段,这里配置应该与上面DownLoadTemplate方法里配置一样)
//如果不设置导入的字段DownLoadTemplateColumns,默认显示所有界面上所有可以看到的字段
DownLoadTemplateColumns = x => new { x.SellNo, x.TranNo, x.Remark, x.CreateDate };
/// <summary>
/// 2022.06.20增加原生excel读取方法(导入时可以自定义读取excel内容)
/// string=当前读取的excel单元格的值
/// ExcelWorksheet=excel对象
/// ExcelRange当前excel单元格对象
/// int=当前读取的第几行
/// int=当前读取的第几列
/// string=返回的值
/// </summary>
ImportOnReadCellValue = (string value, ExcelWorksheet worksheet, ExcelRange excelRange, int rowIndex, int columnIndex) =>
{
string 表头列名 = worksheet.Cells[1, columnIndex].Value?.ToString();
//这里可以返回处理后的值,值最终写入到model字段上
return value;
};
//导入保存前处理(可以对list设置新的值)
ImportOnExecuting = (List<SellOrder> list) =>
{
//设置webResponse.Code = "-1"会中止后面代码执行,与返回 webResponse.Error()一样,区别在于前端提示的是成功或失败
//webResponse.Code = "-1";
//webResponse.Message = "测试强制返回";
//return webResponse.OK("ok");
return webResponse.OK();
};
//导入后处理(已经写入到数据库了)
ImportOnExecuted = (List<SellOrder> list) =>
{
return webResponse.OK();
};
return base.Import(files);
}
2)重写后台表的权限-(只验证登没登陆不校验有没有权限)
- 复制表名,查找对应controller,在对应的partial参考文档链接复制粘贴
文档链接:http://v3.volcore.xyz/dev/%E9%87%8D%E5%86%99%E5%90%8E%E5%8F%B0%E6%8E%A5%E5%8F%A3%E6%9D%83%E9%99%90.html
三、其余记录
1、添加后端controller接口–添加新方法请求映射—参考如下注解和方法
//批量选择获取明商品数据
[Route("getGoods"), HttpPost]
public IActionResult GetGoods([FromBody] PageDataOptions loadData)
{
//调用商品信息的查询方法
var gridData = _goodsService.GetPageData(loadData);
return JsonNormal(gridData);//返回数据-保持大小写一致
//return Json(gridData);不保持大小写一致
}
2、文件-------》Base64字符串
public static string ConvertFileToBase64(string filePath)
{
if (!File.Exists(filePath))
return "文件未找到:" + filePath;
byte[] fileBytes = File.ReadAllBytes(filePath);
string base64String = Convert.ToBase64String(fileBytes);
return base64String;
}
2、前后端请求响应整个流程
//前台请求
handleAuditClick() {
let rows = this.getSelectRows();
if (rows.length > 0) {
//请求后端处理
//传当前选中的所有ID
let updateRows = rows.map((item) => {
return item.PRODUCT_ID;
})
let sendModel = {
tableName: "CY_RD_PRODUCT_INFO",
idName:"PRODUCT_ID",
keys : updateRows,
}
let url = "api/Sys_DbToDb/updateTableHandleFlag";
this.http.post(url,sendModel,true).then(reslut=>{
if (reslut.success) {
this.$Message.success("审核成功");
//审核成功刷新数据
this.refresh()
}else{
this.$Message.error(reslut.MsgContent);
}
})
// this.$Message.error(JSON.stringify(updateRows));
}
else{
this.$Message.error(JSON.stringify("请先选择需要审核的数据"));
}
},
//后台处理
dto参数体
namespace VOL.Entity.DomainModels
{
public class SendModel
{
public string tableName { get; set; }
public string idName { get; set; }
public string[] keys { get; set; }
}
}
控制层
[HttpPost, Route("updateTableHandleFlag"), AllowAnonymous]
public IActionResult updateTableHandleFlag([FromBody] SendModel sendModel)
{
var msg = Service.updateTableHandleFlag(sendModel);
return Content(msg.Serialize());
}
服务层接口
public partial interface ISys_DbToDbService
{
RespMessage updateTableHandleFlag(SendModel sendModel);
}
服务层实现类
public RespMessage updateTableHandleFlag(SendModel sendModel)
{
RespMessage msg = new RespMessage();
try
{
//获取数据连接
var db = DBServerProvider.DbContext.SqlSugarClient;
//遍历执行sql
foreach (var item in sendModel.keys)
{
//sql
//string sql = " update " + sendModel.tableName + " HANDLE_FLAG set = " + ;
string sql = $" update {sendModel.tableName} set HANDLE_FLAG = 'A' where 1=1 and {sendModel.idName} = {item} ";
db.Ado.ExecuteCommand(sql);
msg.MsgContent = "审核标记处理成功";
}
}
catch (Exception ex)
{
msg.success = false;
msg.MsgContent = ex.Message;
Core.Services.Logger.Error(LoggerType.ApiException, msg.MsgContent, ex.Message);
}
return msg;
}