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
我一直在努力解决这个问题。我似乎无法让邮政编码始终看起来像这种格式 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