SQL服务器:如何将包含数字的字符中的字母大写

SQL Server: How to Capitalize Letters in Char Containing Numbers

我一直在努力解决这个问题。我似乎无法让邮政编码始终看起来像这种格式 1234AB。

pc CHAR(6) NOT NULL  
CONSTRAINT CK_pc CHECK( pc LIKE '[1-9][0-9][0-9][0-9][A-Z][A-Z]')

这会完成正确的数字和字母的工作,但不会将最后两个字母大写。

例如: 如果我输入 1234aB,它会完全像那样存储在数据库中,而我希望它像这样存储 1234AB。

我想我需要在这里使用触发器或程序,但我不确定如何使用。

提前致谢!

您必须使用区分大小写的排序规则。例如,假设列 pc CHAR(6) NOT NULL 的排序规则是 SQL_Latin1_General_CP1_CI_AS

SELECT  col.COLLATION_NAME
FROM    INFORMATION_SCHEMA.COLUMNS col
WHERE   col.TABLE_SCHEMA = 'dbo'
AND     col.TABLE_NAME = 'TableA'
AND     col.COLUMN_NAME = 'pc'
-- returns SQL_Latin1_General_CP1_CI_AS

我将使用以下 CHECK 约束以及相同排序规则的 区分大小写 版本(在本例中为 SQL_Latin1_General_CP1_CS_AS):

CREATE TABLE dbo.TableA(
    pc CHAR(6) NOT NULL,
    CONSTRAINT CK_pc CHECK( pc COLLATE SQL_Latin1_General_CP1_CS_AS LIKE N'[1-9][0-9][0-9][0-9][A-Z][A-Z]' )
)
GO

ALTER TABLE dbo.TableA
DROP CONSTRAINT CK_pc
GO
ALTER TABLE dbo.TableA
ADD CONSTRAINT CK_pc CHECK( pc COLLATE SQL_Latin1_General_CP1_CS_AS LIKE N'[1-9][0-9][0-9][0-9][A-Z][A-Z]' )
GO

ALTER TABLE dbo.TableA
DROP CONSTRAINT CK_pc
GO
ALTER TABLE dbo.TableA
ADD CONSTRAINT CK_pc CHECK( pc COLLATE Latin1_General_CS_AS LIKE '[1-9][0-9][0-9][0-9][A-Z][A-Z]' )
GO

然后

INSERT dbo.TableA VALUES ('1234aa')
/*
Msg 547, Level 16, State 0, Line 6
The INSERT statement conflicted with the CHECK constraint "CK_pc15". The conflict occurred in database "Test", table "dbo.Table15", column 'pc'.
The statement has been terminated.
*/
GO

INSERT dbo.TableA VALUES ('1234AA')
/*
(1 row(s) affected)
*/

注意:如我们所见,我们没有(在本例中)更改列的 COLLATION。

您可以使用排序规则使此约束起作用,但它有点古怪。您必须在约束中包含排序规则,但您还必须检查是否相等,因为默认排序规则将被忽略。

create table CapTest
(
    pc char(6) collate SQL_Latin1_General_CP1_CS_AS not null
)

alter table CapTest
add constraint CK_pc  check(pc LIKE '[1-9][0-9][0-9][0-9][A-Z][A-Z]' AND pc = upper(pc)) 


insert CapTest
select '1234AB' --this will work fine

insert CapTest
select '1234Ab' --this will fail the constraint

select * from CapTest

drop table CapTest

--编辑--

从现在开始,您似乎想要实际更改插入的值,您将需要使用触发器而不是约束。以下是如何使用 instead of 触发器执行此操作。

create table CapTest
(
    pc char(6)  not null
)

alter table CapTest
add constraint CK_pc  check(pc LIKE '[1-9][0-9][0-9][0-9][A-Z][A-Z]') 

go

create trigger tr_CapTestInsert on CapTest instead of insert as
begin
    insert CapTest(pc)
    select UPPER(i.pc)
    from inserted i
end

GO

insert CapTest
select '1234AB' union all
select '1234Ab' union all
select '1234aB' union all
select '1234ab' 

select * from CapTest

drop table CapTest

如果您有权访问 INSERT 所在的代码,请像这样使用 UPPER:

INSERT INTO PostalCode (pc) VALUES (UPPER('1234ab'))

如果您无权访问 INSERT 命令所在的代码,您可以删除约束并使用触发器 (CREATE TRIGGER) 以确保存储的数据始终为大写:

CREATE TABLE PostalCode(
    pc CHAR(6) NOT NULL
)

CREATE TRIGGER PostalCode_INSERT_UPDATE
       ON PostalCode
AFTER INSERT, UPDATE
AS
BEGIN
       SET NOCOUNT ON;

       UPDATE PostalCode
        SET pc = UPPER(pc)
        WHERE pc in (SELECT INSERTED.pc FROM INSERTED)

END

INSERT INTO PostalCode
       VALUES('1234ab')

SELECT * FROM PostalCode   

pc
1234AB    

UPDATE PostalCode SET pc = '1234ab' WHERE pc = '1234AB'

SELECT * FROM PostalCode       

pc
1234AB

通常您不会在触发器中执行此操作。您需要创建一个约束(如之前的答案),以便获取的数据始终有效。然后,您可以在代码中创建一个函数(或存储过程)以 return 正确格式化邮政编码。您的案例非常简单,您可以按照其他人的建议使用内置的 sql 函数 upper() 。如果您有更复杂的格式,您可以创建自己的格式。

create function fFormatPostalCode2 
(
    @Code char(6)
)
returns char(6)
as
begin
    return upper(@Code)  -- any other formating here
end

declare @r char(6)
set @r = dbo.fFormatPostalCode('1232aB')
select @r