个人博客 用于记载日常收集的一些技术文章 ...
SQL : 计算 日期段 价格 SQL : 计算 日期段 价格 有一张价目表,字段有:组织名称、物料名称、单位、单价、开始日期、结束日期

有一张明细表,字段有:组织名称、物料名称、单位、单价、日期

想将价目表的单价 填写到 明细表的单价,
关联关系为 组织名称、物料名称、单位 相同,日期 在 开始日期、结束日期 之间,
如果存在重复价格,取价目表的 最后一行

UPDATE d
SET d.单价 = p.单价
FROM 明细表 d
INNER JOIN (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY 组织名称, 物料名称, 单位
ORDER BY 开始日期 DESC, 结束日期 DESC
) as rn
FROM 价目表
WHERE 结束日期 >= (SELECT MIN(日期) FROM 明细表) -- 提前过滤
AND 开始日期 <= (SELECT MAX(日期) FROM 明细表)
) p ON d.组织名称 = p.组织名称
AND d.物料名称 = p.物料名称
AND d.单位 = p.单位
AND d.日期 BETWEEN p.开始日期 AND p.结束日期
AND p.rn = 1; -- 取最后一行

郭少锋 创建 2025-11-28 11:05:02 SQL
SQL : 读取 image 到文件 SQL : 读取 image 到文件
-- 1. 启用高级选项

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;

-- 2. 启用 xp_cmdshell

EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

-- 3. 执行你的命令(例如导出二进制数据)

DECLARE @sql NVARCHAR(1000);
SET @sql = 'BCP "SELECT FCONTENT FROM K3DBConfiger250609.dbo.T_BD_PRODUCTMODEL where FID = ''Kingdee''" queryout "C:\Data\output.txt" -T -N';
EXEC xp_cmdshell @sql;

SELECT FCONTENT FROM K3DBConfiger250609.dbo.T_BD_PRODUCTMODEL where FID = 'Kingdee'

-- 4. 使用后建议关闭(安全考虑)

EXEC sp_configure 'xp_cmdshell', 0;
RECONFIGURE;
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;
郭少锋 创建 2025-10-17 11:59:56 SQL
SQL : 数据库 查找包含文字的 数据表 SQL : 数据库 查找包含文字的 数据表
DECLARE @SearchStr NVARCHAR(100) = '99291303-1d0d-42d2-9c5e-5ce8153172d2' -- 修改为你要查找的字符串
DECLARE @SQL NVARCHAR(MAX)
DECLARE @TableName NVARCHAR(256)
DECLARE @ColumnName NVARCHAR(128)
DECLARE @Schema NVARCHAR(128)
DECLARE @DataType NVARCHAR(128)

-- 创建临时表存储结果

if exists (select * from sys.objects where object_id = object_id(N'dbo.Tmp_FindTxt') and type in (N'U'))
drop table dbo.Tmp_FindTxt


CREATE TABLE Tmp_FindTxt (

SchemaName NVARCHAR(128),
TableName NVARCHAR(256),
ColumnName NVARCHAR(128),
ColumnValue NVARCHAR(MAX),
MatchCount INT -- 修改为MatchCount更准确
)

-- 获取所有字符串类型的列(包括数据类型信息)

DECLARE TableCursor CURSOR FOR
SELECT
s.name AS SchemaName,
t.name AS TableName,
c.name AS ColumnName,
ty.name AS DataType
FROM
sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE
ty.name IN ('nvarchar','varchar','char','nchar','text','ntext') -- and t.name = 'T_META_OBJECTTYPECACHE'

OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @Schema, @TableName, @ColumnName, @DataType

WHILE @@FETCH_STATUS = 0
BEGIN
-- 对text/ntext类型字段特殊处理
IF @DataType IN ('text', 'ntext')
BEGIN
SET @SQL =
'INSERT INTO Tmp_FindTxt (SchemaName, TableName, ColumnName, ColumnValue, MatchCount)
SELECT
''' + REPLACE(@Schema, '''', '''''') + ''',
''' + REPLACE(@TableName, '''', '''''') + ''',
''' + REPLACE(@ColumnName, '''', '''''') + ''',
CAST(SUBSTRING(CAST(' + QUOTENAME(@ColumnName) + ' AS NVARCHAR(MAX)), 1, 100) AS NVARCHAR(100)),
COUNT(*) AS MatchCount
FROM
' + QUOTENAME(@Schema) + '.' + QUOTENAME(@TableName) + '
WHERE
CAST(' + QUOTENAME(@ColumnName) + ' AS NVARCHAR(MAX)) LIKE ''%' + REPLACE(@SearchStr, '''', '''''') + '%''
GROUP BY
CAST(' + QUOTENAME(@ColumnName) + ' AS NVARCHAR(MAX))'
END
ELSE
BEGIN
SET @SQL =
'INSERT INTO Tmp_FindTxt (SchemaName, TableName, ColumnName, ColumnValue, MatchCount)
SELECT
''' + REPLACE(@Schema, '''', '''''') + ''',
''' + REPLACE(@TableName, '''', '''''') + ''',
''' + REPLACE(@ColumnName, '''', '''''') + ''',
CAST(' + QUOTENAME(@ColumnName) + ' AS NVARCHAR(MAX)),
COUNT(*) AS MatchCount
FROM
' + QUOTENAME(@Schema) + '.' + QUOTENAME(@TableName) + '
WHERE
' + QUOTENAME(@ColumnName) + ' LIKE ''%' + REPLACE(@SearchStr, '''', '''''') + '%''
GROUP BY
' + QUOTENAME(@ColumnName)
END

BEGIN TRY
EXEC sp_executesql @SQL
END TRY
BEGIN CATCH
PRINT 'Error searching [' + @Schema + '].[' + @TableName + '].[' + @ColumnName + ']: ' + ERROR_MESSAGE()
END CATCH

FETCH NEXT FROM TableCursor INTO @Schema, @TableName, @ColumnName, @DataType
END

CLOSE TableCursor
DEALLOCATE TableCursor

-- 显示结果

SELECT

'select '+ ColumnName +' ,* from '+ TableName +' where '+ ColumnName +' like ''%' + REPLACE(@SearchStr, '''', '''''') + '%''' AS '查询',

SchemaName AS '架构名',
TableName AS '表名',
ColumnName AS '字段名',
ColumnValue AS '包含的字段值',
MatchCount AS '匹配行数'
FROM
Tmp_FindTxt
ORDER BY
SchemaName, TableName, ColumnName

结果:

查询 架构名 表名 字段名 包含的字段值 匹配行数
select FID ,* from T_META_OBJECTTYPECACHE where FID like '%99291303-1d0d-42d2-9c5e-5ce8153172d2%' dbo T_META_OBJECTTYPECACHE FID 99291303-1d0d-42d2-9c5e-5ce8153172d2 1
郭少锋 编辑 2025-10-16 11:05:11 创建 2025-10-16 11:04:35 SQL
SQL : 读取 xml 字段 SQL : 读取 xml 字段
------------------------------------------------------------------------------------------------------------------------
-- 读取 xml 成 table

select * from (
--------------------------------------------------------------------------------------------
select

a1.value('(Seq)[1]', 'int') AS Seq,
a1.value('(FUserId/User/Id)[1]', 'int') AS UserId,
a1.value('(FUserId/User/Name)[1]', 'nvarchar(50)') AS UserName,
a1.value('(FType)[1]', 'nvarchar(50)') AS FType,
a1.value('(FValue)[1]', 'int') AS FValue

from t_Bas_SysParameter

cross apply FParameters.nodes('/FHead/FEntity/FEntity') T(a1)

where FParameterObjId = 'aGsf_SysSet'
--------------------------------------------------------------------------------------------
) a where UserName = '郭少锋'




/*
select FParameters from t_Bas_SysParameter where FParameterObjId = 'aGsf_SysSet'

------------------------------------------------------------------------------------------------------------------------
-- 取得 xml

<FHead>
<FEntity>
<FEntity>
<Id>1</Id>
<Seq>1</Seq>
<FUserId_Id>100076</FUserId_Id>
<FUserId>
<User>
<Id>100076</Id>
<Name>郭少锋</Name>
<UserAccount>gsf</UserAccount>
</User>
</FUserId>
<FType>年</FType>
<FValue>1</FValue>
</FEntity>
<FEntity>
<Id>2</Id>
<Seq>2</Seq>
<FUserId_Id>133043</FUserId_Id>
<FUserId>
<User>
<Id>133043</Id>
<Name>测试</Name>
<UserAccount>cs</UserAccount>
</User>
</FUserId>
<FType>月</FType>
<FValue>2</FValue>
</FEntity>
</FEntity>
</FHead>
------------------------------------------------------------------------------------------------------------------------
*/
郭少锋 编辑 2025-10-09 17:24:28 创建 2025-10-09 17:11:30 SQL
SQL : 日期对比 SQL : 日期对比 sql2012 +

select dateFromParts(2021,1,1) 数字转日期 ,(case when dateFromParts(2021,1,1) > '2025-1-2' then '大于' else '小于等于' end) 日期对比

select max( dateFromParts( FYear ,FPeriod ,1) ) from t_RP_ContactBal where FRP = 0 and ( FYear * 12 + FPeriod <= 2021 * 12 + 1 )

sql2008

select max( convert(nvarchar(10) ,FYear) +'-'+ right( '000'+ convert(nvarchar(10) ,FPeriod) ,2) ) from t_RP_ContactBal where FRP = 0 and ( FYear * 12 + FPeriod <= 2021 * 12 + 1 )

郭少锋 编辑 2025-09-26 15:38:45 创建 2025-09-24 14:47:22 SQL
SQL : 链接服务器 SQL : 链接服务器 -- 创建链接服务器

EXEC master.dbo.sp_addlinkedserver

@server = N'Link_188_10',

@srvproduct = N'',
@provider = N'SQLNCLI',

@datasrc = N'192.168.188.10' -- 数据库地址: 192.168.1.100\SQL2019
go

-- 配置登录凭据

EXEC master.dbo.sp_addlinkedsrvlogin

@rmtsrvname = N'Link_188_10', -- 链接名

@useself = N'False',
@locallogin = NULL,

@rmtuser = N'sa', -- 用户名
@rmtpassword = N'sql2019' -- 密码
go

-- 测试连接:链接数据库

SELECT name FROM Link_188_10.master.sys.databases


select * from Link_188_10.KIS_U_42.dbo.t_ItemClass
go



-- 查询所有链接服务器

EXEC sp_linkedservers
go

-- 查询特定链接服务器的信息

EXEC sp_helpserver N'Link_188_10'
go

-- 查询链接服务器的表

select * from Link_188_10.KIS_U_42.dbo.t_ItemClass
go


-- 先删除登录映射

EXEC master.dbo.sp_droplinkedsrvlogin

@rmtsrvname = N'Link_188_10',
@locallogin = NULL


-- 再删除链接服务器

EXEC master.dbo.sp_dropserver

@server = N'Link_188_10',
@droplogins = 'droplogins'



郭少锋 编辑 2025-08-08 11:37:24 创建 2025-08-08 11:26:44 SQL
SQL : 分组 逐行累计 SQL : 分组 逐行累计 select
a.FStockName,a.FMtrlNo,a.FMtrlName,a.FUnitStockName
,a.FIdentityId
,a.FQtyStock4

,sum(b.FQtyStock4) FQtyStock4_Sum

from TMP2983AE495E5511F0ACB40050563 a
join TMP2983AE495E5511F0ACB40050563 b on ( b.FStockName = a.FStockName ) and ( b.FMtrlNo = a.FMtrlNo ) and ( b.FMtrlName = a.FMtrlName ) and ( b.FUnitStockName = a.FUnitStockName )

and ( b.FIdentityId <= a.FIdentityId )

group by
a.FStockName,a.FMtrlNo,a.FMtrlName,a.FUnitStockName
,a.FIdentityId
,a.FQtyStock4

order by a.FStockName,a.FMtrlNo,a.FMtrlName,a.FUnitStockName ,a.FIdentityId
;



SELECT
a.group_column,
a.date_column,
a.value_column,
SUM(b.value_column) AS group_running_total
FROM your_table a
JOIN your_table b ON
b.group_column = a.group_column
AND b.date_column < a.date_column
GROUP BY
a.group_column,
a.date_column,
a.value_column
ORDER BY a.group_column, a.date_column;
郭少锋 编辑 2025-07-11 21:43:13 创建 2025-07-11 21:07:36 SQL
SQL : 数字前面加 0 SQL : 数字前面加 0 DECLARE @num INT = 123;
DECLARE @length INT = 6;

SELECT REPLACE(STR(@num, @length), ' ', '0');
-- 结果: '000123'
郭少锋 创建 2025-07-11 00:23:49 SQL
SQL : 开通端口 防火墙设置 SQL : 开通端口 防火墙设置 要让其他电脑访问 SQL Server,需要在 **SQL Server 配置** 和 **网络/防火墙设置** 上进行配置。以下是详细步骤:

---

## **1. 确保 SQL Server 已启用 TCP/IP 协议**
### **步骤 1:打开 SQL Server 配置管理器**
1. 按 `Win + R`,输入 `SQLServerManager<版本号>.msc`(如 `SQLServerManager15.msc` 适用于 SQL Server 2019)。
- 或通过 **控制面板 → 管理工具 → SQL Server 配置管理器** 打开。

2. 展开 **SQL Server 网络配置** → **协议**(对应实例,如 `MSSQLSERVER` 或命名实例)。
- 如果是默认实例(`MSSQLSERVER`),直接选择 `MSSQLSERVER` 下的 **协议**。
- 如果是命名实例(如 `SQLEXPRESS`),选择对应实例名的 **协议**。

3. 确保 **TCP/IP** 协议已启用(右键 → **启用**)。
- 如果未启用,右键 **TCP/IP** → **启用**,然后重启 SQL Server 服务。

---

### **步骤 2:配置 TCP/IP 端口**
1. 右键 **TCP/IP** → **属性** → **IP 地址** 选项卡。
2. 找到 `IPAll` 部分:
- **TCP 端口**:确保已设置端口(默认 `1433`,可修改为其他端口如 `1688`)。
- **TCP 动态端口**:如果不需要动态端口,留空或删除数值。
3. 如果是命名实例,默认可能使用动态端口(如 `1688`),建议固定端口(如 `1433`)。

---

### **步骤 3:重启 SQL Server 服务**
1. 在 **SQL Server 服务** 中(SQL Server 配置管理器 → 服务):
- 右键 **SQL Server (实例名)** → **重新启动**。
2. 确保服务状态变为 **“正在运行”**。

---

## **2. 检查 Windows 防火墙设置**
SQL Server 默认端口(如 `1433`)需要放行,否则外部无法访问。

### **方法 1:允许 SQL Server 端口通过防火墙**
1. 打开 **Windows Defender 防火墙**(或第三方防火墙如火绒)。
2. 进入 **高级设置** → **入站规则** → **新建规则**。
3. 选择 **端口** → 点击 **下一步**。
4. 选择 **TCP**,并输入端口号(如 `1433` 或自定义端口)→ 点击 **下一步**。
5. 选择 **允许连接** → 点击 **下一步**。
6. 根据需要勾选适用的网络类型(域、专用、公用)→ 点击 **下一步**。
7. 输入规则名称(如 `SQL Server Port 1433`)→ 完成。

### **方法 2:直接放行 `sqlservr.exe`**
1. 在 **入站规则** 中新建规则 → 选择 **程序** → 点击 **下一步**。
2. 浏览到 SQL Server 主程序路径(默认):
```
C:\Program Files\Microsoft SQL Server\MSSQLXX.MSSQLSERVER\MSSQL\Binn\sqlservr.exe
```
- `XX` 是 SQL Server 版本号(如 `MSSQL15` 对应 SQL Server 2019)。
3. 允许连接 → 完成规则。

---

## **3. 检查 SQL Server 身份验证模式**
默认情况下,SQL Server 可能仅允许 **Windows 身份验证**,需启用 **SQL Server 和 Windows 身份验证模式**。

### **步骤 1:修改身份验证模式**
1. 打开 **SQL Server Management Studio (SSMS)**,连接 SQL Server。
2. 右键服务器实例 → **属性** → **安全性** 选项卡。
3. 选择 **SQL Server 和 Windows 身份验证模式** → 点击 **确定**。
4. 重启 SQL Server 服务(必须重启才能生效)。

---

### **步骤 2:创建 SQL Server 登录账户**
1. 在 SSMS 中,展开 **安全性 → 登录名**。
2. 右键 → **新建登录名**。
3. 输入用户名(如 `sa` 或自定义账户)。
4. 在 **服务器角色** 中勾选 `sysadmin`(谨慎操作,仅限管理员)。
5. 在 **用户映射** 中勾选目标数据库,并分配权限。
6. 点击 **确定** 保存。

---

## **4. 测试外部连接**
### **方法 1:使用 SQL Server Management Studio (SSMS)**
1. 在另一台电脑上打开 SSMS。
2. 输入服务器名称:
- **本地网络**:`服务器IP,端口`(如 `192.168.1.100,1433`)。
- **主机名**:如果 DNS 可解析,可直接用主机名(如 `SQLServer01`)。
- 如果是命名实例,格式为 `服务器IP\实例名,端口`(如 `192.168.1.100\SQLEXPRESS,1433`)。
3. 选择身份验证方式:
- **SQL Server 身份验证**:输入用户名和密码。
- **Windows 身份验证**:需确保网络信任关系。

---

### **方法 2:使用命令行测试**
在另一台电脑上运行:
```cmd
sqlcmd -S 服务器IP,端口 -U 用户名 -P 密码
```
示例:
```cmd
sqlcmd -S 192.168.1.100,1433 -U sa -P 123456
```
如果成功,会显示 `1>` 提示符。

---

## **5. 其他注意事项**
### **5.1 检查 SQL Server 是否监听正确 IP**
1. 在 SSMS 中运行以下查询:
```sql
EXEC xp_readerrorlog 0, 1, 'Server is listening on';
```
- 确认输出中包含目标 IP 和端口(如 `0.0.0.0:1433` 或 `[::]:1433` 表示监听所有 IPv4/IPv6 地址)。

2. 如果仅监听 `127.0.0.1`(本地回环),需修改 SQL Server 配置:
- 在 **SQL Server 配置管理器** → **TCP/IP 属性** → **IP 地址** 选项卡:
- 确保 `IPAll` 的 `TCP 动态端口` 为空,`TCP 端口` 设置为固定值(如 `1433`)。
- 确保所有 `IPx`(如 `IP1`、`IP2`)的 **已启用** 设为 **是**。

---

### **5.2 检查网络连通性**
1. 在客户端电脑上测试是否能 ping 通 SQL Server:
```cmd
ping 服务器IP
```
2. 测试端口是否开放:
```cmd
telnet 服务器IP 1433
```
- 如果未安装 `telnet`,可通过 **控制面板 → 程序 → 启用或关闭 Windows 功能** 安装。

---

### **5.3 命名实例的特殊配置**
如果使用命名实例(如 `SQLEXPRESS`):
1. 确保 **SQL Server Browser 服务** 已启动:
- 在 **服务管理器** 中找到 `SQL Server Browser`,设置为 **自动启动** 并启动服务。
2. 客户端连接时需指定实例名:
- 格式:`服务器IP\实例名,端口`(如 `192.168.1.100\SQLEXPRESS,1433`)。

---

## **6. 常见问题解决**
| 问题 | 解决方案 |
|------|----------|
| **无法连接,提示“拒绝连接”** | 检查防火墙、SQL Server 是否运行、身份验证模式。 |
| **连接超时** | 检查网络连通性(ping/端口测试),确保 SQL Server 监听正确 IP。 |
| **仅限本地访问** | 检查 SQL Server 是否绑定到 `127.0.0.1`,修改为 `0.0.0.0`。 |
| **命名实例无法连接** | 确保 SQL Server Browser 服务运行,并正确指定实例名。 |

---

## **总结步骤**
1. **启用 TCP/IP 协议** 并固定端口(如 `1433`)。
2. **放行防火墙端口** 或 `sqlservr.exe`。
3. **启用 SQL Server 身份验证模式** 并创建登录账户。
4. **测试网络连通性**(ping/端口测试)。
5. **客户端使用 `IP,端口` 或 `IP\实例名,端口` 连接**。

如果仍有问题,请提供具体的错误信息以便进一步排查!
郭少锋 创建 2025-05-08 11:21:19 SQL
SQL : 以多个字段分组 将某个字段的不同值 合并成一串字符(逗号分隔) SQL : 以多个字段分组 将某个字段的不同值 合并成一串字符(逗号分隔) # MSSQL 以多个字段分组并将某个字段的不同值合并成一串字符(逗号分隔)

select *

,isnull( stuff((

select ',' + FCreator

from ( select distinct FBillNo_Rpt,FSeq_Rpt,FBillNo_PpBom,FMtrlNo2,FUnitName2,FScrapRate,FDenominator ,FCreator from TMP69E1ED8B1F7811F0ACC00050563_1 where FCreator != '' ) t2

where t1.FBillNo_Rpt = t2.FBillNo_Rpt and t1.FSeq_Rpt = t2.FSeq_Rpt
and t1.FBillNo_PpBom = t2.FBillNo_PpBom
and t1.FMtrlNo2 = t2.FMtrlNo2 and t1.FUnitName2 = t2.FUnitName2
and t1.FScrapRate = t2.FScrapRate
and t1.FDenominator = t2.FDenominator

for xml path('')

), 1, 1, '') ,'') as FCreatorTxt

from TMP69E1ED8B1F7811F0ACC00050563 t1





在MSSQL中,你可以使用STRING_AGG函数(SQL Server 2017及更高版本)或FOR XML PATH方法(旧版本)来实现按多个字段分组并将某个字段的不同值合并成逗号分隔的字符串。

## 方法1:使用STRING_AGG函数(SQL Server 2017+)

```sql
SELECT
field1,
field2,
field3,
STRING_AGG(DISTINCT value_field, ',') AS concatenated_values
FROM
your_table
GROUP BY
field1, field2, field3;
```

## 方法2:使用FOR XML PATH方法(SQL Server 2005+)

```sql
SELECT
field1,
field2,
field3,
STUFF((
SELECT ',' + value_field
FROM your_table t2
WHERE t1.field1 = t2.field1
AND t1.field2 = t2.field2
AND t1.field3 = t2.field3
FOR XML PATH('')
), 1, 1, '') AS concatenated_values
FROM
your_table t1
GROUP BY
field1, field2, field3;
```

## 示例

假设有一个订单明细表,你想按客户ID和订单日期分组,合并所有产品名称:

```sql
-- 使用STRING_AGG
SELECT
CustomerID,
CONVERT(date, OrderDate) AS OrderDate,
STRING_AGG(DISTINCT ProductName, ', ') AS Products
FROM
OrderDetails
GROUP BY
CustomerID, CONVERT(date, OrderDate);

-- 使用FOR XML PATH
SELECT
CustomerID,
CONVERT(date, OrderDate) AS OrderDate,
STUFF((
SELECT ', ' + ProductName
FROM OrderDetails t2
WHERE t1.CustomerID = t2.CustomerID
AND CONVERT(date, t1.OrderDate) = CONVERT(date, t2.OrderDate)
FOR XML PATH('')
), 1, 2, '') AS Products
FROM
OrderDetails t1
GROUP BY
CustomerID, CONVERT(date, OrderDate);
```

注意:
1. STRING_AGG是更现代、更简洁的方法
2. 如果需要去除重复值,STRING_AGG可以直接使用DISTINCT关键字
3. FOR XML PATH方法需要手动处理第一个逗号(使用STUFF函数)
4. 两种方法都可以添加排序:STRING_AGG使用WITHIN GROUP,FOR XML PATH在子查询中添加ORDER BY
郭少锋 编辑 2025-04-22 21:17:17 创建 2025-04-22 20:44:52 SQL