从SQL

时间:2016-01-14 15:47:54

标签: sql variables

尝试查看索引在SQL中的工作方式。这不是一张桌子,而是更多的清单?在C#或其他语言中,我们使用array[i]作为获取特定项的语法的数组。我如何获取5号ID?这是基本代码,我打算将其放入更大的代码中,例如递增for循环以递增每个ID。目的:从记录历史记录表中删除需要太长时间并影响生产。希望将其批量处理为较小的事务以删除过时的记录。

DECLARE @Cust_NoHolds TABLE(IDs VARCHAR(100))
INSERT INTO @Cust_NoHolds SELECT '0'
INSERT INTO @Cust_NoHolds SELECT '1'
INSERT INTO @Cust_NoHolds SELECT '2'
INSERT INTO @Cust_NoHolds SELECT '3'
INSERT INTO @Cust_NoHolds SELECT '4'
INSERT INTO @Cust_NoHolds SELECT '5'
INSERT INTO @Cust_NoHolds SELECT '6'
INSERT INTO @Cust_NoHolds SELECT '7'
INSERT INTO @Cust_NoHolds SELECT '8'
INSERT INTO @Cust_NoHolds SELECT '9'

SELECT IDs FROM @Cust_NoHolds WITH (INDEX(1)) --this is obviously wrong

6 个答案:

答案 0 :(得分:3)

关系数据库表没有自然顺序 - 与一个逻辑上有一个项目的数组不同,数据库行与另一行没有关系。它看起来就像选择数据时那样,因为它以某种方式存储和检索,但这是数据库实现的结果。

因此,在数据库术语中,删除第5行并不是很有意义,但是删除按行XXX排序数据时出现的第5行是有意义的。虽然在实践中您倾向于删除列XXX具有值YYY的行(或行集)。

您可以将某个索引视为在某个表格上强加某种顺序(但这并不是它们的主要目的)。

答案 1 :(得分:3)

如果您想跟踪表格上的广告订单顺序,请使用identity列:

DECLARE @Cust_NoHolds TABLE(
    id int identity,
    IDs VARCHAR(100)
);

然后对于插入,使用显式列列表:

INSERT INTO @Cust_NoHolds(ids) SELECT '0' --crude, but basic. forgive me.

现在,您有一个具有插入顺序的单调递增数字。因此,获得第五条记录的一种方法是:

select *
from @Cust_NoHolds
order by id
offset 4
fetch first 1 row only;

对于offset,0是第一行,所以4是第五行。 SQL Server 2012+中提供了此语法;在早期版本中,您需要使用子查询两次TOP。此外,order by很重要,因为除非order by子句指定了排序,否则结果集(如表)是无序的。

请注意,标识列保证会增加,但它们可能会有间隙。

答案 2 :(得分:1)

我将把这些烂摊子放在这里,以提供一个例子(并提醒自己),无论我们编写多长时间,总会有经验教训。我要非常感谢Conrad Frix,Pieter Geerkens,Gordon Linoff和目的地数据让我从另一个角度来看待这个问题。我的目标是将这个大型任务批量化为较小的任务,我可以在单独的单个查询中进行管理。以下是我的想法,它非常适合我想要完成的任务。再次感谢前面提到的这个主题的贡献者,以及其他每个人都在尝试。下面使用SQL体系结构优于数组,并且看起来比我的“数组模拟”原型更有效。

DECLARE @Cust_NoHolds TABLE(IDs VARCHAR(100))
INSERT INTO @Cust_NoHolds
SELECT  DISTINCT CI.Custodian_Id
FROM            custodian_info          CI
--WHERE "stuff" (it's a massive union of two massive join statements)

DECLARE @historyIDs TABLE(histIDs VARCHAR(100)) --New values with each batch run!
INSERT INTO @historyIDs
    SELECT  Custodian_History_Id
    FROM    custodian_history   CH
    WHERE   CH.Custodian_Id IN (Select IDs FROM @Cust_NoHolds)

--SELECT * FROM @historyIDs ORDER BY histIDs --takes 29 seconds to get to this point

DELETE  custodian_history
FROM    custodian_history   CH
WHERE   CH.Custodian_History_Id IN (Select TOP 100 histIDs FROM @historyIDs) --TOP X represents my batch
--Re-running this full sql file will take on the next X IDs in sequence, effectively making a functional batch.

答案 3 :(得分:0)

一种方法是使用TOP限制已删除记录的数量。

示例数据

/* Table variables making sharing sample data easy.
 */
DECLARE @Sample TABLE
    (
        Id        INT
    )
;

INSERT INTO @Sample
    (
        Id
    )
VALUES
    (1),
    (2),
    (3)
;

此查询是在SQL Server 2008 R2中构建和测试的。如果它不起作用,请在问题中添加正确的产品标签。

/* You can limit the number of records that are deleted.
 */     
DELETE TOP (1)
FROM
    @Sample
;

/* Two of the original three records will remain.
 * There is no guarantee which these will be.
 */
SELECT
    *
FROM
    @Sample
;

此查询删除三个示例记录中的一个并返回另外两个。您可以与WHILE结合使用,直到删除了所有必需的记录。

编辑:您可能会发现更好的方法是确定原始查询效果不佳的原因。 Stack DBA可以提供帮助,如果您可以提供查询计划和某些背景信息。

答案 4 :(得分:0)

如果您可以从另一个表或表中识别要删除的记录,则可以将此逻辑移到delete语句中。这种方法避免了循环,这对SQL的优势没有影响。

示例使用两个表。 @Target是我们要删除的表。 @ToDelete包含@Target中不再需要的行。

示例数据

/* Table variables making sharing sample data easy.
 */
DECLARE @Target TABLE
    (
        Id        INT
    )
;

DECLARE @ToDelete TABLE
    (
        Id        INT
    )
;

INSERT INTO @Target
    (
        Id
    )
VALUES
    (1),
    (2),
    (3)
;

INSERT INTO @ToDelete
    (
        Id
    )
VALUES
    (1),
    (2)
;

在示例中,我已过滤@ToDelete以限制已删除的记录。

示例

/* You can use the WHERE clause to filter the 
 * records you are going to delete.
 */
DELETE
FROM
    @Target
FROM
    @Target AS t
        INNER JOIN @ToDelete AS td        ON td.Id = t.Id
WHERE
    td.Id = 2
;

/* Id 2 has been removed.
 * It appeared in both tables and the WHERE clause of the DELETE statement.
 */
SELECT
    *
FROM
    @Target
;

答案 5 :(得分:-1)

尽管有关如何在SQL中使用数组的争论,但在这里,孩子们......在SQL中是一个“数组”。 SQL Server 2008

+-------+-----------+-----------+-----------+
|   own |   success |   fail    |   pending |
+-------+-----------+-----------+-----------+
|   BN  |       3   |       0   |       0   |
|   BB  |       2   |       1   |       0   |
|   BD  |       1   |       1   |       1   |
|   BC  |       0   |       0   |       1   |