【问题标题】:How to convert numeric to nvarchar in SQL Server?如何在 SQL Server 中将数字转换为 nvarchar?
【发布时间】:2019-05-06 01:16:16
【问题描述】:

考虑下表。我使用触发器添加到表中。在数字转字符串那一栏,失败了。

CREATE TABLE [dbo].[tblAIAgent]
(
    [AgentCode] [NVARCHAR](10) NOT NULL,
    [NationalCode] [BIGINT] NOT NULL 
         CONSTRAINT [DF_tblAIAgent_NationalCode]  DEFAULT ((0)),
    [FirstName] [NVARCHAR](50) NOT NULL 
         CONSTRAINT [DF_tblAIAgent_Name] DEFAULT (''),
    [LastName] [NVARCHAR](50) NOT NULL 
         CONSTRAINT [DF_tblAIAgent_Family] DEFAULT (''),
    [IsActive] [BIT] NOT NULL 
         CONSTRAINT [DF_tblAIAgent_Active] DEFAULT ((1)),
    [Counter] [INT] IDENTITY(1,1) NOT NULL,

    CONSTRAINT [PK_tblAIAgent] 
        PRIMARY KEY CLUSTERED 
)

ALTER TRIGGER [dbo].[AgentInsert] 
ON [dbo].[tblAIAgent]
INSTEAD OF INSERT
AS
BEGIN
    DECLARE @AgentCode NVARCHAR(10)
    DECLARE @NationalCode BIGINT
    DECLARE @FirstName NVARCHAR(50)
    DECLARE @LastName NVARCHAR(50)
    DECLARE @IsActive BIT
    DECLARE @CounterIs INT

    SET @CounterIs = @@IDENTITY

    SELECT
        @AgentCode = AgentCode,
        @NationalCode = NationalCode,
        @FirstName = FirstName,
        @LastName = LastName,
        @IsActive = IsActive 
    FROM inserted

    INSERT INTO tblAIAgent (NationalCode, FirstName, LastName, IsActive, AgentCode)
    VALUES (@NationalCode, @FirstName, @LastName, @IsActive, 'Agent_' + CAST(@CounterIs AS NVARCHAR(4))) 
END

【问题讨论】:

  • @@IDENTITY 在插入 after 之前没有值 - 所以在你的例子中它将是 null ...所以如果你想这样做方式,这似乎过于复杂,您必须在插入之后将AgentCode 更新为单独的语句。为什么不只使用计算列?无论如何,你想用这个触发器来完成什么?它似乎没有做任何事情?而且它坏了,你不能假设inserted 表中只有一条记录。

标签: sql sql-server tsql triggers calculated-columns


【解决方案1】:

这里有几个问题:

@@IDENTITY 是一个系统函数,包含在完成INSERTSELECT INTOBULK COPY 语句时生成的最后一个标识值。如果该语句不影响任何具有标识列的表,则@@IDENTITY 返回NULL。如果插入多行,生成多个标识值,@@IDENTITY 返回最后生成的标识值。

在你的情况下,你有一个INSTEAD OF INSERT 触发器,所以没有INSERT

下面的查询是完全错误的并且会给出错误的结果,它只有在插入一行时才能按预期工作,如果多于 1 行,那么这些变量将只保存一行的值,您将丢失其他行的其他值,导致伪 INSERTED 可能包含 1 或更多行

select @AgentCode=AgentCode,
       @NationalCode=NationalCode,
       @FirstName=FirstName,
       @LastName=LastName,
       @IsActive=IsActive 
from inserted

现在,查看您的表格,您已经有一个 IDENTITY 列,因此您根本不需要 TRIGGER,您只需将计算列设为

CREATE TABLE [dbo].[tblAIAgent](
    [AgentCode] AS 'Agent_' + CAST([Counter] AS VARCHAR(10)),
    [NationalCode] [bigint] NOT NULL 
    CONSTRAINT [DF_tblAIAgent_NationalCode]  DEFAULT ((0)),
    [FirstName] [nvarchar](50) NOT NULL 
    CONSTRAINT [DF_tblAIAgent_Name]  DEFAULT (''),
    [LastName] [nvarchar](50) NOT NULL 
    CONSTRAINT [DF_tblAIAgent_Family]  DEFAULT (''),
    [IsActive] [bit] NOT NULL 
    CONSTRAINT [DF_tblAIAgent_Active]  DEFAULT ((1)),
    [Counter] [int] IDENTITY(1,1) NOT NULL,
    CONSTRAINT [PK_tblAIAgent] PRIMARY KEY ([Counter])
    );

更新:

根据您的评论 “不能再选择计算列作为 PK。我希望将此列作为 FK 放置在其他相关表中。我编写触发器来获取列值而不是计算列,以便我可以选择该列作为主键”。您正在尝试将其设为PRIMARY KEY,以便您可以这样做

CREATE TABLE T(
  Counter INT IDENTITY(1,1) NOT NULL,
  OtherCol INT,
  Computed AS CONCAT('Agent_', CAST(Counter AS VARCHAR(10))) PERSISTED,
  CONSTRAINT PKT PRIMARY KEY(Computed)
);

CREATE TABLE TT(
  ReferenceComputedColumn VARCHAR(16) NOT NULL,
  OtherColumn INT,
  CONSTRAINT FK_ReferencedComputedColumn 
      FOREIGN KEY(ReferenceComputedColumn) 
      REFERENCES T(Computed)
)

INSERT INTO T(OtherCol) VALUES
(1), (2), (3);

INSERT INTO TT(ReferenceComputedColumn, OtherColumn) VALUES
('Agent_1', 10),
('Agent_3', 20);

SELECT *
FROM T LEFT JOIN TT 
ON T.Computed = TT.ReferenceComputedColumn;

See how it's working.

另请参阅 Paul White 的这篇文章 Properly Persisted Computed Columns

【讨论】:

  • 计算列不能再被选为 PK。我希望将此列作为 FK 放置在其他相关表中。我编写了触发器来获取列值而不是计算列,以便我可以选择该列作为主键。
【解决方案2】:

试试这个

SELECT CONVERT(NVARCHAR(255), @AgentCode)

【讨论】:

    【解决方案3】:
    SELECT CAST([PictureId] AS NVARCHAR(4)) From Category
    

    【讨论】:

    • 请编辑您的答案并使用“示例代码”以提高可读性。
    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    相关资源
    最近更新 更多