Ann*_*tta 4 sql-server sql-standard
大约一个月前,我刚刚开始了一份新工作,为一家人手不足的软件公司工作。我的任务是对一些旧的非 ansi SQL 代码进行现代化改造,我在尝试破解这个问题时遇到了特别困难的时间。我最近刚毕业,所以我对现代 SQL 标准有点熟悉,并且根据我所做的研究,不推荐使用的部分与非 ansi 连接 *= 相关。我已经尝试了几乎所有我能想到的改变这个烂摊子的方法,但我不知所措。谢谢你的协助。
Select @SQLCmd =
'SELECT ''' + @InvType + ''' AS Inv_Type, ' + @TableName + '_Number AS Item_Number, Alternate_ID, Description1, ' +
'Company_ID, Department_ID, Group_Id, Section_Id, Media_Code, ' +
'Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, ' + @TableName + '.Retention_Code, ' +
'Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status ' +
'FROM ' + @TableName + ', RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS ' +
'Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV ' +
'WHERE ' + @TableName + '.Retention_Code *= RETENTION.Retention_Code AND ' +
@TableName + '_Number *= RESV.Item_Number AND ''' + @InvType + ''' = RESV.Item_Type ' +
Case LTrim(@RetnType)
When '' Then ''
Else 'AND ' + @TableName + '.Retention_Type = ''' + @RetnType + ''''
End
+ ' AND ' + @WhereCond +
' UNION ' +
'SELECT ''' + @InvType + ''' AS Inv_Type, ' + @TableName + '_Number AS Item_Number, Alternate_ID, Description1, ' +
'Company_ID, Department_ID, Group_Id, Section_Id, Media_Code, ' +
'Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, ' + @TableName + '.Retention_Code, ' +
'Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status ' +
'FROM ' + @TableName + ', RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS ' +
'Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV ' +
'WHERE ' + @TableName + '.Retention_Code *= RETENTION.Retention_Code AND ' +
@TableName + '_Number *= RESV.Item_Number AND ''' + @InvType + ''' = RESV.Item_Type ' +
Case LTrim(@RetnType)
When '' Then ''
Else 'AND ' + @TableName + '.Retention_Type = ''' + @RetnType + ''''
End
Run Code Online (Sandbox Code Playgroud)
考虑这两个简单的表:
CREATE TABLE dbo.t1
(
t1_ID int NOT NULL
);
CREATE TABLE dbo.t2
(
t2_ID int NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
JOINsSQL Server 2000 及更早版本中使用的“旧样式” ,如下所示:
SELECT *
FROM dbo.t1
, dbo.t2
WHERE t1.t1_ID *= t2.t2_ID;
Run Code Online (Sandbox Code Playgroud)
等效于 ANSI 样式LEFT JOIN:
SELECT *
FROM dbo.t1
LEFT JOIN dbo.t2 ON t1.t1_ID = t2.t2_ID;
Run Code Online (Sandbox Code Playgroud)
这个:
SELECT *
FROM dbo.t1
, dbo.t2
WHERE t1.t1_ID =* t2.t2_ID;
Run Code Online (Sandbox Code Playgroud)
变成:
SELECT *
FROM dbo.t1
RIGHT JOIN dbo.t2 ON t1.t1_ID = t2.t2_ID;
Run Code Online (Sandbox Code Playgroud)
虽然,我不喜欢使用RIGHT JOIN,并且会将其重写为等效的LEFT JOIN,如下所示:
SELECT *
FROM dbo.t2
LEFT JOIN dbo.t1 ON t2.t2_ID = t1.t1_ID;
Run Code Online (Sandbox Code Playgroud)
您问题中的动态 SQL 足够复杂,我首先使用它PRINT来打印生成代码的示例,然后我将使用上述规则将旧样式连接转换为符合 ANSI 标准的连接。
我从你的代码中模拟了以下内容,试图简化它:
DECLARE @SQLCmd nvarchar(max);
DECLARE @InvType nvarchar(100) = 'InvType';
DECLARE @TableName nvarchar(128) = 'TableName';
DECLARE @RetnType nvarchar(100) = 'RetnType';
DECLARE @WhereCond nvarchar(1000) = 'WhereCond';
Select @SQLCmd =
'SELECT ''' + @InvType + ''' AS Inv_Type, ' + @TableName + '_Number AS Item_Number, Alternate_ID, Description1,
Company_ID, Department_ID, Group_Id, Section_Id, Media_Code,
Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, ' + @TableName + '.Retention_Code,
Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status
FROM ' + @TableName + ', RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS
Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV
WHERE ' + @TableName + '.Retention_Code *= RETENTION.Retention_Code AND ' +
@TableName + '_Number *= RESV.Item_Number AND ''' + @InvType + ''' = RESV.Item_Type
' +
Case LTrim(@RetnType)
When '' Then ''
Else 'AND ' + @TableName + '.Retention_Type = ''' + @RetnType + ''''
End
+ '
AND ' + @WhereCond +
' UNION
SELECT ''' + @InvType + ''' AS Inv_Type, ' + @TableName + '_Number AS Item_Number, Alternate_ID, Description1,
Company_ID, Department_ID, Group_Id, Section_Id, Media_Code,
Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, ' + @TableName + '.Retention_Code,
Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status
FROM ' + @TableName + ', RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS
Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV
WHERE ' + @TableName + '.Retention_Code *= RETENTION.Retention_Code AND
' + @TableName + '_Number *= RESV.Item_Number AND ''' + @InvType + ''' = RESV.Item_Type
' +
Case LTrim(@RetnType)
When '' Then ''
Else 'AND ' + @TableName + '.Retention_Type = ''' + @RetnType + ''''
End
PRINT @SQLCmd;
Run Code Online (Sandbox Code Playgroud)
这导致:
SELECT 'InvType' AS Inv_Type, TableName_Number AS Item_Number, Alternate_ID, Description1,
Company_ID, Department_ID, Group_Id, Section_Id, Media_Code,
Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, TableName.Retention_Code,
Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status
FROM TableName, RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS
Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV
WHERE TableName.Retention_Code *= RETENTION.Retention_Code AND TableName_Number *= RESV.Item_Number AND 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
AND WhereCond UNION
SELECT 'InvType' AS Inv_Type, TableName_Number AS Item_Number, Alternate_ID, Description1,
Company_ID, Department_ID, Group_Id, Section_Id, Media_Code,
Location_Current, Location_Home, Hold_Status, Record_Type, Disposition_Status, TableName.Retention_Code,
Retn_Disposal_Method, Retn_Authorize_Code, Reservation_Status
FROM TableName, RETENTION, (SELECT Item_Type, Item_Number, MAX(Reservation_Process_Status) AS
Reservation_Status FROM RESERVATION GROUP BY Item_Type, Item_Number) AS RESV
WHERE TableName.Retention_Code *= RETENTION.Retention_Code AND
TableName_Number *= RESV.Item_Number AND 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
Run Code Online (Sandbox Code Playgroud)
我会重新格式化,以便每一列都在单独的行上:
SELECT 'InvType' AS Inv_Type
, TableName_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, TableName.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM TableName
, RETENTION
, (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type, Item_Number
) AS RESV
WHERE TableName.Retention_Code *= RETENTION.Retention_Code
AND TableName_Number *= RESV.Item_Number
AND 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
AND WhereCond
UNION
SELECT 'InvType' AS Inv_Type
, TableName_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, TableName.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM TableName
, RETENTION
, (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type
, Item_Number
) AS RESV
WHERE TableName.Retention_Code *= RETENTION.Retention_Code
AND TableName_Number *= RESV.Item_Number
AND 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
Run Code Online (Sandbox Code Playgroud)
有点乏味,但现在我们可以看到查询实际做了什么。
将“旧式”连接转换为 ANSI 式连接会导致:
SELECT 'InvType' AS Inv_Type
, TableName_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, TableName.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM TableName
LEFT JOIN RETENTION ON TableName.Retention_Code = RETENTION.Retention_Code
LEFT JOIN (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type, Item_Number
) AS RESV ON TableName_Number = RESV.Item_Number
WHERE 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
AND WhereCond
UNION
SELECT 'InvType' AS Inv_Type
, TableName_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, TableName.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM TableName
LEFT JOIN RETENTION ON TableName.Retention_Code = RETENTION.Retention_Code
LEFT JOIN (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type
, Item_Number
) AS RESV ON TableName_Number = RESV.Item_Number
WHERE 'InvType' = RESV.Item_Type
AND TableName.Retention_Type = 'RetnType'
Run Code Online (Sandbox Code Playgroud)
将其折叠回动态 SQL 会导致:
DECLARE @SQLCmd nvarchar(max);
DECLARE @TableName nvarchar(128);
DECLARE @InvType nvarchar(100);
DECLARE @RetnType nvarchar(100);
DECLARE @WhereCond nvarchar(1000);
SET @SQLCmd = 'SELECT ''' + @InvType + ''' AS Inv_Type
, TableName_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, TableName.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM ' + @TableName + '
LEFT JOIN RETENTION ON ' + @TableName + '.Retention_Code = RETENTION.Retention_Code
LEFT JOIN (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type, Item_Number
) AS RESV ON TableName_Number = RESV.Item_Number
WHERE ' + @InvType + ' = RESV.Item_Type
AND ' + @TableName + '.Retention_Type = ''' + @RetnType + '''
AND ' + @WhereCond + '
UNION
SELECT ''' + @InvType + ''' AS Inv_Type
, ' + @TableName + '_Number AS Item_Number
, Alternate_ID
, Description1
, Company_ID
, Department_ID
, Group_Id
, Section_Id
, Media_Code
, Location_Current
, Location_Home
, Hold_Status
, Record_Type
, Disposition_Status
, ' + @TableName + '.Retention_Code
, Retn_Disposal_Method
, Retn_Authorize_Code
, Reservation_Status
FROM ' + @TableName + '
LEFT JOIN RETENTION ON ' + @TableName + '.Retention_Code = RETENTION.Retention_Code
LEFT JOIN (
SELECT Item_Type
, Item_Number
, MAX(Reservation_Process_Status) AS Reservation_Status
FROM RESERVATION
GROUP BY Item_Type
, Item_Number
) AS RESV ON ' + @TableName + '_Number = RESV.Item_Number
WHERE ''' + @InvType + ''' = RESV.Item_Type
AND TableName.Retention_Type = ''' + @RetnType + ''''
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
121 次 |
| 最近记录: |