Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL Server中为同一表中的两行交换值_Sql_Sql Server - Fatal编程技术网

在SQL Server中为同一表中的两行交换值

在SQL Server中为同一表中的两行交换值,sql,sql-server,Sql,Sql Server,我想交换表中两行的值。我有两行的行ID。有什么疑问吗?这里有一个例子。在查询之前,我有以下内容: row1 : 1,2,3 row2 : 5,6,7 交换后,我希望: row1 : 5,6,7 row2 : 1,2,3 如果要将两个已知ID的值从一行交换到另一行,请尝试以下操作: --need to store the original values SELECT *,CASE WHEN id=123 then 987 ELSE 123 END AS JoinId INTO #T

我想交换表中两行的值。我有两行的行ID。有什么疑问吗?这里有一个例子。在查询之前,我有以下内容:

row1 : 1,2,3 row2 : 5,6,7 交换后,我希望:

row1 : 5,6,7 row2 : 1,2,3
如果要将两个已知ID的值从一行交换到另一行,请尝试以下操作:

--need to store the original values
SELECT
    *,CASE WHEN id=123 then 987 ELSE 123 END AS JoinId
    INTO #Temp
    FROM YourTable
    WHERE ID in (123,987)

--swap values
UPDATE y
    SET col1=t.col1
        ,col2=t.col2
    FROM YourTable        y
        INNER JOIN #Temp  t ON y.id =t.JoinId
    WHERE ID in (123,987)
简单的更新工作:

UPDATE myTable
SET 
col1 = CASE WHEN col1 = 1 THEN 5 ELSE 1 END,
col2 = CASE WHEN col2 = 2 THEN 6 ELSE 2 END,
col3 = CASE WHEN col3 = 3 THEN 7 ELSE 3 END 

结果:行值被交换。

我最近遇到了一个类似的问题,我有一个列用于对输出进行排序,并希望允许移动顺序。我在寻找答案,突然发现了这个问题。这并没有充分回答我的特定问题,但也许我的解决方案会帮助其他人

我的数据库看起来是这样的

表:订单表

Index_Column,Order_Column,Text
1           ,1           ,"Second Test text"
2           ,2           ,"First Test text"
我希望能够在php中使用pdo交换它们。 最终,我找到了一种使用一个SQL查询的方法

UPDATE `Order_Table` AS o 
INNER JOIN (SELECT `Index_Column`, `Order_Column` FROM `Order_Table` 
WHERE `Index_Column` IN (:Index1,:Index2)) 
AS t ON o.`Index_Column` <> t.`Index_Column` 
SET o.`Order_Column` = t.`Order_Column` 
WHERE o.`Index_Column` IN (:Index1,:Index2)

您不一定需要使用表的ID列,我相信您可以使用适当的连接逻辑按任何列进行搜索。将表连接到表本身是一个技巧。

您需要根据WHERE条件选择所有记录, 然后设置“按案例更新”条件

UPDATE tbl_Temp SET 
fk_userType = CASE fk_userType WHEN 1 THEN 2 WHEN 2 THEN 1 END,
fk_userRole = CASE fk_userRole WHEN 1 THEN 2 WHEN 2 THEN 1 END
WHERE (fk_userType = 1 AND fk_userRole = 1) OR (fk_userType = 2 AND fk_userRole = 2);

上面的例子都不实用。。。它应该类似于以下更新部分:

/*******************************************************************************/
/*  DATA TABLE IS PREPARING                                                    */
/*******************************************************************************/
IF EXISTS (SELECT TOP 1 * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TEST' AND TABLE_SCHEMA = 'dbo')
DROP TABLE [dbo].[TEST];

CREATE TABLE [dbo].[TEST](
  [ID]       int           IDENTITY(1,1) NOT NULL,
  [Name]     varchar(50)   NULL,
  [Surname]  varchar(50)   NULL,
  [AGE]      int           NULL,
  CONSTRAINT [PK_TEST] PRIMARY KEY CLUSTERED 
    ( [ID] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/*******************************************************************************/
/*  INSERTING TEST VALUES                                                      */
/*******************************************************************************/
INSERT INTO dbo.TEST (Name, Surname, AGE)
SELECT 'Sevim'        , 'PARLAYAN' , 36   UNION ALL
SELECT 'Uğur'         , 'PARLAYAN' , 41   UNION ALL
SELECT 'Berkan Cahit' , 'PARLAYAN' , 17   UNION ALL
SELECT 'Miray Çağla'  , 'PARLAYAN' , 6    ;

SELECT * FROM dbo.TEST ORDER BY ID;


-- At this point maybe the trigger can be disabled...

/*******************************************************************************/
/*  I'm swapping Uğur and Sevim rows (So, rows into 1 and 2 do swapping )...   */
/*******************************************************************************/
UPDATE  TT
SET     TT.Name     = ZZZ.Name
     ,  TT.Surname  = ZZZ.Surname
     ,  TT.AGE      = ZZZ.AGE
FROM     dbo.TEST as TT
JOIN     (
           SELECT TOP 1 * FROM dbo.TEST WHERE ID = 2 /* Big key value first     */  UNION ALL
           SELECT TOP 1 * FROM dbo.TEST WHERE ID = 1 /* Then small key value... */
         ) as ZZZ on ZZZ.ID in (1, 2)
WHERE   TT.ID in (1, 2) ;

-- At this point maybe the trigger can be activated...

SELECT * FROM dbo.TEST ORDER BY ID

如果您只需要交换几行,那么,是的,您可以使用定制的case语句和join语句来强制执行它,就像其他答案中一样。但是如果你需要在很多行上做手术,那将是一件痛苦的事

一个简单、可扩展的解决方案 注释

您可以进行两行交换、多行交换和复制。它很灵活。 根据需要指定尽可能多的目标/源行对。仅更新目标行。 指定要复制的列。只有那些列将被更新。 没有要清理的临时桌子。 它很容易重用,因为行ID列在一个明显的地方。
如果只有一个值必须在两行之间交换:

UPDATE task t1 SET ordre = (SELECT ordre FROM task t2 WHERE t1.id <> t2.id AND id IN (26,25)) WHERE id IN (26,25)

第一次读你的问题时,我以为你想复制一行,但现在我开始认为你想更新一行中的值,使之等于另一行中的值。。。但我不明白你问题的“反之亦然”部分。你能举一些例子来帮助澄清你的问题吗?反之亦然,这意味着我还需要用行更新的数据来更新我从中获取数据的行。例如:行1:1,2,3行2:5,6,7完成后,我想要行1:5,6,7行2:1,2,3我希望你能理解。@AmRoSH:我重写了你的问题,以便更容易理解。我希望我做得正确,否则请重新编辑。以后你应该尽量把问题写清楚,这样可以更快地得到更高质量的答案。感谢KM,这个查询适用于多行,这意味着如果这些ID是外键,我需要交换它们的行。如果要交换的列是外键或纯数据,这应该适用。@JanakThakkar,我尝试从不更新主键。正确处理所有外键是一件非常痛苦的事情。如果您没有约束问题FK,PK,那么您可以更新PK,这取决于您需要/想要什么。这是在2010年写的,我认为在更现代的SQL Server版本中,使用表变量而不是临时表运行会更好。如果我只使用您的查询更新一列,是否可以交换整个原始数据?因为我只使用您的查询更新了一列,而它交换了整行。
WITH map AS (
    SELECT *
    FROM (VALUES
        (1, 2),  -- Here's an example of swapping two rows:
        (2, 1),  -- 1 <- 2,  2 <- 1

        (3, 4),  -- Here's an example of rotating three rows:
        (4, 5),  -- 3 <- 4,  4 <- 5,  5 <- 3
        (5, 3),

        (6, 7)   -- Here's an example of just copying one row to another: 3 <- 5
    ) AS a (destID, srcID)
)
UPDATE destination
SET
    ColumnA = source.ColumnA,
    ColumnB = source.ColumnB,
    ColumnC = source.ColumnC
FROM
    SomeTable AS destination
    JOIN map ON map.destID = destination.ID
    JOIN SomeTable AS source ON source.ID = map.srcID
UPDATE task t1 SET ordre = (SELECT ordre FROM task t2 WHERE t1.id <> t2.id AND id IN (26,25)) WHERE id IN (26,25)