如何在SQL服务器中自动将YES/NO转换成BIT?
How to convert YES/NO to BIT automatically in SQL Server?
我想覆盖 SQL 服务器中系统定义的转换。可以吗
问题陈述
我有一个很大的 csv 文件来上传数据库中的数据。有一个 BIT
类型的列包含 True/False
、Yes/No
、1/0
当我使用批量插入时 True/False
并且“1/0”将被视为正确的值,但 Yes/No
(如预期的那样)将引发转换错误。
有没有什么方法可以在没有任何循环或一个值一个值的情况下转换 Yes/No
?
编辑
自定义数据类型PanelMemberType
CREATE TYPE [dbo].[PanelMemberType] AS TABLE(
[Email] [nvarchar](255) NOT NULL,
[LocationName] [nvarchar](255) NOT NULL,
[OptInPermission] [nvarchar](255) NOT NULL
)
GO
存储过程代码:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
@tblPanelMember PanelMemberType READONLY,
@PanelID int,
@UserID nvarchar(128)
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING @tblPanelMember p2 ON p1.Email= p2.Email
WHEN MATCHED THEN
UPDATE SET
p1.PanelID = @PanelID,
p1.LocationID = (SELECT TOP(1) [LocationID]
FROM [dbo].[Location]
WHERE [LocationName] = p2.LocationName),
p1.Email = p2.Email,
p1.OptInPermission = CONVERT(BIT, p2.OptInPermission),
p1.DateAdded = p1.DateAdded,
p1.DateLastUpdated = (SELECT GETDATE()),
p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES (@PanelID, (SELECT TOP(1) [LocationID]
FROM [dbo].[Location]
WHERE [LocationName] = p2.LocationName),
p2.Email, CONVERT(BIT, p2.OptInPermission),
(SELECT GETDATE()));
END
首先将 CSV 文件中的记录插入暂存 table。
然后 运行 实际插入您的 table 和您的 select 语句应该如下所示:
INSERT INTO ActualTable(column1, column2, column3)
SELECT column1
, column2
, CAST(CASE column3
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE column3
END AS BIT) AS YourBitColumn
FROM StagingTable;
根据您的方法,这应该有效:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
(
@tblPanelMember PanelMemberType READONLY
, @PanelID INT
, @UserID NVARCHAR(128)
)
AS
BEGIN TRY
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING @tblPanelMember p2
ON p1.Email = p2.Email
WHEN MATCHED THEN
UPDATE
SET p1.PanelID = @PanelID
, p1.LocationID = (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p1.Email = p2.Email
, p1.OptInPermission = CONVERT(BIT, CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission
END)
, p1.DateAdded = p1.DateAdded
, p1.DateLastUpdated = GETDATE()
, p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES
(
@PanelID
, (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p2.Email
, CONVERT(BIT, CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission
END)
, GETDATE()
);
END TRY
BEGIN CATCH
THROW;
END CATCH
您不能覆盖默认函数,但您可以编写自己的函数。例如:
CREATE FUNCTION dbo.ConvertBit
(
@Input VARCHAR(5)
)
RETURNS TABLE AS RETURN
SELECT CONVERT(BIT, CASE @Input
WHEN 'True' THEN 1
WHEN 'Yes' THEN 1
WHEN '1' THEN 1
WHEN 'False' THEN 0
WHEN 'No' THEN 0
WHEN '0' THEN 0
END AS BitColumn;
然后这样查询就可以了:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
(
@tblPanelMember PanelMemberType READONLY
, @PanelID INT
, @UserID NVARCHAR(128)
)
AS
BEGIN TRY
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING (
SELECT T.Email
, T.LocationName
, B.OptInPermission
FROM @tblPanelMember AS T
CROSS APPLY dbo.ConvertBit(T.OptInPermission) AS B(OptInPermission)
) AS p2
ON p1.Email = p2.Email
WHEN MATCHED THEN
UPDATE
SET p1.PanelID = @PanelID
, p1.LocationID = (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p1.Email = p2.Email
, p1.OptInPermission = p2.OptInPermission
, p1.DateAdded = p1.DateAdded
, p1.DateLastUpdated = GETDATE()
, p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES
(
@PanelID
, (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p2.Email
, p2.OptInPermission
, GETDATE()
);
END TRY
BEGIN CATCH
THROW;
END CATCH
只需多应用一点逻辑,而不是试图盲目地转换为 bit
:
p1.OptInPermission = convert( bit,
CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission END)
(或者,为了避免在 MERGE
的两个分支中重复此逻辑,请在源代码中执行:
USING (select Email,LocationName,convert( bit,
CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission END as OptInPermission from @tblPanelMember) p2
)
我想覆盖 SQL 服务器中系统定义的转换。可以吗
问题陈述
我有一个很大的 csv 文件来上传数据库中的数据。有一个 BIT
类型的列包含 True/False
、Yes/No
、1/0
当我使用批量插入时 True/False
并且“1/0”将被视为正确的值,但 Yes/No
(如预期的那样)将引发转换错误。
有没有什么方法可以在没有任何循环或一个值一个值的情况下转换 Yes/No
?
编辑
自定义数据类型PanelMemberType
CREATE TYPE [dbo].[PanelMemberType] AS TABLE(
[Email] [nvarchar](255) NOT NULL,
[LocationName] [nvarchar](255) NOT NULL,
[OptInPermission] [nvarchar](255) NOT NULL
)
GO
存储过程代码:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
@tblPanelMember PanelMemberType READONLY,
@PanelID int,
@UserID nvarchar(128)
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING @tblPanelMember p2 ON p1.Email= p2.Email
WHEN MATCHED THEN
UPDATE SET
p1.PanelID = @PanelID,
p1.LocationID = (SELECT TOP(1) [LocationID]
FROM [dbo].[Location]
WHERE [LocationName] = p2.LocationName),
p1.Email = p2.Email,
p1.OptInPermission = CONVERT(BIT, p2.OptInPermission),
p1.DateAdded = p1.DateAdded,
p1.DateLastUpdated = (SELECT GETDATE()),
p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES (@PanelID, (SELECT TOP(1) [LocationID]
FROM [dbo].[Location]
WHERE [LocationName] = p2.LocationName),
p2.Email, CONVERT(BIT, p2.OptInPermission),
(SELECT GETDATE()));
END
首先将 CSV 文件中的记录插入暂存 table。
然后 运行 实际插入您的 table 和您的 select 语句应该如下所示:
INSERT INTO ActualTable(column1, column2, column3)
SELECT column1
, column2
, CAST(CASE column3
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE column3
END AS BIT) AS YourBitColumn
FROM StagingTable;
根据您的方法,这应该有效:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
(
@tblPanelMember PanelMemberType READONLY
, @PanelID INT
, @UserID NVARCHAR(128)
)
AS
BEGIN TRY
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING @tblPanelMember p2
ON p1.Email = p2.Email
WHEN MATCHED THEN
UPDATE
SET p1.PanelID = @PanelID
, p1.LocationID = (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p1.Email = p2.Email
, p1.OptInPermission = CONVERT(BIT, CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission
END)
, p1.DateAdded = p1.DateAdded
, p1.DateLastUpdated = GETDATE()
, p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES
(
@PanelID
, (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p2.Email
, CONVERT(BIT, CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission
END)
, GETDATE()
);
END TRY
BEGIN CATCH
THROW;
END CATCH
您不能覆盖默认函数,但您可以编写自己的函数。例如:
CREATE FUNCTION dbo.ConvertBit
(
@Input VARCHAR(5)
)
RETURNS TABLE AS RETURN
SELECT CONVERT(BIT, CASE @Input
WHEN 'True' THEN 1
WHEN 'Yes' THEN 1
WHEN '1' THEN 1
WHEN 'False' THEN 0
WHEN 'No' THEN 0
WHEN '0' THEN 0
END AS BitColumn;
然后这样查询就可以了:
ALTER PROCEDURE [dbo].[PanelMemberBulkUpdate]
(
@tblPanelMember PanelMemberType READONLY
, @PanelID INT
, @UserID NVARCHAR(128)
)
AS
BEGIN TRY
SET NOCOUNT ON;
MERGE INTO PanelMember p1
USING (
SELECT T.Email
, T.LocationName
, B.OptInPermission
FROM @tblPanelMember AS T
CROSS APPLY dbo.ConvertBit(T.OptInPermission) AS B(OptInPermission)
) AS p2
ON p1.Email = p2.Email
WHEN MATCHED THEN
UPDATE
SET p1.PanelID = @PanelID
, p1.LocationID = (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p1.Email = p2.Email
, p1.OptInPermission = p2.OptInPermission
, p1.DateAdded = p1.DateAdded
, p1.DateLastUpdated = GETDATE()
, p1.LastUpdateUserID = @UserID
WHEN NOT MATCHED THEN
INSERT (PanelID, LocationID, Email, OptInPermission, DateAdded)
VALUES
(
@PanelID
, (SELECT TOP (1) [LocationID] FROM [dbo].[Location] WHERE [LocationName] = p2.LocationName)
, p2.Email
, p2.OptInPermission
, GETDATE()
);
END TRY
BEGIN CATCH
THROW;
END CATCH
只需多应用一点逻辑,而不是试图盲目地转换为 bit
:
p1.OptInPermission = convert( bit,
CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission END)
(或者,为了避免在 MERGE
的两个分支中重复此逻辑,请在源代码中执行:
USING (select Email,LocationName,convert( bit,
CASE p2.OptInPermission
WHEN 'Yes' THEN 1
WHEN 'No' THEN 0
ELSE p2.OptInPermission END as OptInPermission from @tblPanelMember) p2
)