合并并进行顺序编号

huangapple go评论49阅读模式
英文:

MERGE with Sequential Numbering

问题

I have a table with several fields which includes a column called "apporder," which is just an integer. The value is used for the order in which it is displayed on the front end. So it would be like 1, 2, 3, 4, etc.

I am trying to merge new values into that table, and each new insert should be 1 higher than the max.

This is what I am trying, but it is always inserting the max value + 1 from the table, not taking into account any new rows inserted. How can I accomplish this.

MERGE INTO table2 USING
(SELECT field1, field2, apporder FROM table1) a ON a.field1 = table2.field1
WHEN NOT MATCHED THEN
INSERT
(
field1,
field2,
apporder
)
VALUES
(
'a',
'b',
(SELECT ISNULL(MAX(apporder), 0) + 1 FROM table2)
)

英文:

I have a table with several fields which includes a column called apporder which is just an integer. The value is used for the order in which it is displayed on the front end. So it would be like 1, 2, 3, 4, etc.

I am trying to merge new values into that table, and each new insert should be 1 higher than the max.

This is what I am trying, but it is always inserting the max value + 1 from the table, not taking into account any new rows inserted. How can I accomplish this.

MERGE INTO table2 USING
	(SELECT field1,field2,apporder FROM table1) a ON a.field1 = table2.field1
WHEN NOT MATCHED TEHN
	INSERT
		(
			field1,
			field2,
			apporder
		)
	VALUES
		(
			'a',
			'b',
			(SELECT ISNULL(MAX(apporder),0) + 1 FROM table2)
		)

答案1

得分: 1

看起来你想要一个根据 field1 分组的编号列。但是 MERGE 不会这样做,它只是简单地识别单个匹配行(如果有的话),然后进行更新或插入操作。相反,只需使用普通的 INSERT

要做到这一点而不遇到并发问题,你需要在子查询上使用 UPDLOCKSERIALIZABLE 提示。你将锁定每个完整的组,并且显然如果有人删除一行,你将会得到空缺。

你还需要考虑同时插入多行的情况。你可以使用 ROW_NUMBER 来实现这一点。

INSERT table2
  (field1, field2, apporder)
SELECT
  t1.field1,
  t1.field2,
  (
   SELECT ISNULL(MAX(t2.apporder), 0)
   FROM table2 t2 WITH (UPDLOCK, SERIALIZABLE)
   WHERE t2.field1 = t1.field1
  ) + ROW_NUMBER() OVER (PARTITION BY t1.field1 ORDER BY t1.field2)
FROM table1 t1;

如果可能的话,最好完全放弃这个列,并在查询表时使用 ROW_NUMBER 计算它。

SELECT
  t2.field1,
  t2.field2,
  apporder = ROW_NUMBER() OVER (PARTITION BY t1.field1 ORDER BY t1.field2)
FROM table2 t2
WHERE t2.field1 = 'something';
英文:

It looks like you want some kind of numbering column grouped by field1. But MERGE does not do this, it simply identifies a single matching row if any, and updates or inserts it. Instead just use a normal INSERT.

To do this without running into concurrency problems, you are going to need the UPDLOCK and SERIALIZABLE hints on the subquery. You are going to end up locking each complete group, and obviously you will get holes if anyone deletes a row.

You also need to take into account multiple rows being inserted at once. You can use ROW_NUMBER for this.

INSERT table2
  (field1, field2, apporder)
SELECT
  t1.field1,
  t1.field2,
  (
   SELECT ISNULL(MAX(t2.apporder), 0)
   FROM table2 t2 WITH (UPDLOCK, SERIALIZABLE)
   WHERE t2.field1 = t1.field1
  ) + ROW_NUMBER() OVER (PARTITION BY t1.field1 ORDER BY t1.field2)
FROM table1 t1;

If possible, you should just forgo this column completely, and instead calculate it using ROW_NUMBER when you query the table

SELECT
  t2.field1,
  t2.field2,
  apporder = ROW_NUMBER() OVER (PARTITION BY t1.field1 ORDER BY t1.field2)
FROM table2 t2
WHERE t2.field1 = 'something';

答案2

得分: -1

根据您提供的内容,我理解您首先需要从table2中获取最大的apporder值,然后将其加1,然后在插入新行的INSERT语句中包含该值,并确保它们始终以比当前最大值更高的值插入,即使同时插入了新行。

以下是翻译的内容:

CREATE TABLE YourTable (
  field1 VARCHAR(255),
  field2 VARCHAR(255),
  apporder INT
);

CREATE TABLE YourTable2 (
  field1 VARCHAR(255),
  field2 VARCHAR(255),
  apporder INT
);
INSERT INTO YourTable (field1, field2, apporder)
VALUES
  ('Data 1', 'Value 1', 1),
  ('Data 2', 'Value 2', 2),
  ('Data 3', 'Value 3', 3),
  ('Data 4', 'Value 4', 4);
INSERT INTO YourTable2 (field1, field2, apporder)
VALUES
  ('Data 1', 'Value 1', 10),
  ('Data 2', 'Value 2', 22),
  ('Data 6', 'Value 3', 35),
  ('Data 5', 'Value 4', 42);
MERGE INTO YourTable2 AS tgt
USING (
  SELECT field1, field2, MAX(apporder) AS maxAppOrder
  FROM YourTable
  GROUP BY field1, field2
) AS src ON tgt.field1 = src.field1 AND tgt.field2 = src.field2
WHEN NOT MATCHED THEN
  INSERT (field1, field2, apporder)
  VALUES (src.field1, src.field2, src.maxAppOrder + 1);
SELECT * FROM YourTable
SELECT * FROM YourTable2

fiddle

英文:

Based on what you provided, I am assuming that you first need to get the maximum apporder value from table2 and increment it by 1 then include that value in the INSERT statement when inserting the new rows and make sure that they will always be inserted with a value higher than the current maximum value, even if new rows have been inserted concurrently.

CREATE TABLE YourTable (
  field1 VARCHAR(255),
  field2 VARCHAR(255),
  apporder INT
);

CREATE TABLE YourTable2 (
  field1 VARCHAR(255),
  field2 VARCHAR(255),
  apporder INT
);
INSERT INTO YourTable (field1, field2, apporder)
VALUES
  ('Data 1', 'Value 1', 1),
  ('Data 2', 'Value 2', 2),
  ('Data 3', 'Value 3', 3),
  ('Data 4', 'Value 4', 4);
4 rows affected
INSERT INTO YourTable2 (field1, field2, apporder)
VALUES
  ('Data 1', 'Value 1', 10),
  ('Data 2', 'Value 2', 22),
  ('Data 6', 'Value 3', 35),
  ('Data 5', 'Value 4', 42);
4 rows affected
MERGE INTO YourTable2 AS tgt
USING (
  SELECT field1, field2, MAX(apporder) AS maxAppOrder
  FROM YourTable
  GROUP BY field1, field2
) AS src ON tgt.field1 = src.field1 AND tgt.field2 = src.field2
WHEN NOT MATCHED THEN
  INSERT (field1, field2, apporder)
  VALUES (src.field1, src.field2, src.maxAppOrder + 1);
2 rows affected
SELECT * FROM YourTable
SELECT * FROM YourTable2
field1 field2 apporder
Data 1 Value 1 1
Data 2 Value 2 2
Data 3 Value 3 3
Data 4 Value 4 4
field1 field2 apporder
Data 1 Value 1 10
Data 2 Value 2 22
Data 6 Value 3 35
Data 5 Value 4 42
Data 3 Value 3 4
Data 4 Value 4 5

fiddle

huangapple
  • 本文由 发表于 2023年6月9日 01:18:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定