首页 > 解决方案 > 如何模拟变量、循环和串联以在 SQLite 中协同工作?

问题描述

我被 SQLite 的局限性和它的一些表的设计所困。这是我想要实现的目标:

  1. 创建一个变量来跟踪循环的迭代次数。然后使用此变量在循环期间帮助创建唯一的表行。还将其作为文字计数值插入记录中。
  2. 将所述变量连接到现有字符串以创建可以多次引用的唯一 ID。
  3. 循环代码使用先前的变量来跟踪迭代,并将先前的串联作为 ID,用于为每个循环插入新行。255 个循环是一个任意数字,我怀疑在 99.9% 的情况下我需要 255 个循环,但希望在需要它们的情况下避免失败。我实际上正在查看最少 50 个循环,100 个是罕见的最大值。200 可能更接近真正的最大异常值。255只是为了安全。

这是我到目前为止所尝试的:

DECLARE @cnt INT = 1;

WHILE @cnt < 256
BEGIN
    @seyield = 'BUILDING_STOCK_EXCHANGE_YIELD_' + @cnt;
    @secitizens = 'BUILDING_STOCK_EXCHANGE_CITIZENS_' + @cnt;
    @secount = 'COUNT_CITIZENS_' + @cnt;

    INSERT INTO
        BuildingModifiers (BuildingType, ModifierId)
    VALUES
        ('BUILDING_STOCK_EXCHANGE', @seyield);

    INSERT INTO
        Modifiers (ModifierId, ModifierType, RunOnce, Permanent, SubjectRequirementSetId)
    VALUES
        (@seyield, 'MODIFIER_BUILDING_YIELD_CHANGE', 0, 0, @secitizens);

    INSERT INTO
        ModifierArguments (ModifierID, Name, Value)
    VALUES
        (@seyield, 'BuildingType', 'BUILDING_STOCK_EXCHANGE'),
        (@seyield, 'Amount', '2'),
        (@seyield, 'YieldType', 'YIELD_GOLD');

    INSERT INTO
        RequirementSets(RequirementSetId, RequirementSetType)
    VALUES
        (@secitizens, 'REQUIREMENT_TEST_ALL');

    INSERT INTO
        RequirementSetRequirements(RequirementSetId, RequirementId)
    VALUES
        (@secitizens, @secount);

    INSERT INTO
        Requirements(RequirementId, RequirementType)
    VALUES
        (@secount, 'REQUIREMENT_COLLECTION_ATLEAST');

    INSERT INTO
        RequirementArguments(RequirementId, Name, Value)
    VALUES
        (@secount, 'CollectionType', 'COLLECTION_CITY_PLOT_YIELDS'),
        (@secount, 'Count', @cnt);

   SET @cnt = @cnt + 1;
END;

当然,由于 SQLite 的限制,这不起作用。

是否有任何有效的解决方法?

我知道一个,但几乎不可行:省略循环、变量和连接,并手动复制和粘贴此代码块,每次手动更改相关字段。但是,对于我需要附加行的每个不同的 BUILDING_TYPE,这将需要 255 次复制和粘贴乘以大约 8 或 9 倍。如果有更快更有效的方法,我宁愿不这样做!

标签: sqlite

解决方案


您可以通过递归CTE和使用临时表来做到这一点:

drop table if exists temp.temptable;
create temporary table temptable(cnt int, seyield text, secitizens text, secount text);

with
  recursive constants as (
    select 
      'BUILDING_STOCK_EXCHANGE_YIELD_' seyield,
      'BUILDING_STOCK_EXCHANGE_CITIZENS_' secitizens,
      'COUNT_CITIZENS_' secount  
  ),
  numbers as (
    select 1 cnt
    from constants
    union all
    select cnt + 1 from numbers
    where cnt < 255
  ),
  cte as (
    select
      n.cnt cnt,
      c.seyield || n.cnt seyield,
      c.secitizens || n.cnt secitizens,
      c.secount || n.cnt secount 
    from numbers n cross join constants c
  )  

insert into temptable
select * from cte;

INSERT INTO BuildingModifiers (BuildingType, ModifierId)
SELECT 'BUILDING_STOCK_EXCHANGE', seyield FROM temptable;

INSERT INTO Modifiers (ModifierId, ModifierType, RunOnce, Permanent, SubjectRequirementSetId)
SELECT seyield, 'MODIFIER_BUILDING_YIELD_CHANGE', 0, 0, secitizens FROM temptable;

INSERT INTO ModifierArguments (ModifierID, Name, Value)
SELECT seyield, 'BuildingType', 'BUILDING_STOCK_EXCHANGE' FROM temptable
UNION ALL
SELECT seyield, 'Amount', '2' FROM temptable
UNION ALL
SELECT seyield, 'YieldType', 'YIELD_GOLD' FROM temptable;

INSERT INTO RequirementSets(RequirementSetId, RequirementSetType)
SELECT secitizens, 'REQUIREMENT_TEST_ALL' FROM temptable;

INSERT INTO RequirementSetRequirements(RequirementSetId, RequirementId)
SELECT secitizens, secount FROM temptable;

INSERT INTO Requirements(RequirementId, RequirementType)
SELECT secount, 'REQUIREMENT_COLLECTION_ATLEAST' FROM temptable;

INSERT INTO RequirementArguments(RequirementId, Name, Value)
SELECT secount, 'CollectionType', 'COLLECTION_CITY_PLOT_YIELDS' FROM temptable
UNION ALL
SELECT secount, 'Count', cnt FROM temptable;

请参阅演示


推荐阅读