我的MYSQL v5.7.9数据库中有三个表:
world1:
player_id | city_id | wood_max_level | wheat_max_level | gold_max_level | meat_max_level
world2:
player_id | city_id | wood_max_level | wheat_max_level | gold_max_level | meat_max_level
升级: world | player_id | city_id | building | level
内部升级:
building
包含一个字符串:' wood_max_level',' wheat_max_level',' gold_max_level'或者' meat_max_level'
world
还包含一个字符串:' world1'或者' world2'。
我尝试做的是从升级中选择building
和level
。
然后,我想根据world1
包含的内容更新world2
或world
,并将level
设置为构建中包含的列名。
以下是
我在upgrading
内有一行看起来像这样:
world | player_id | city_id | building | level
'world1' | 190 | 1 | 'wood_max_level'| 2
执行查询后,我会让表格world1
受到影响,因为它已在upgrading
内设置为列world
。 world1
会是这样的:
player_id | city_id | wood_max_level | wheat_max_level | gold_max_level | meat_max_level
190 | 1 | 2 | 0 | 0 | 0
我已经有了一个有效的PHP版本'这个的。基本上我做了第一个查询然后返回一个数组和foreach元素我做了另一个查询。
修改
SELECT
@world := world,
@building := building,
@level := level FROM upgrading;
UPDATE @world
SET @building = @level;
上面我已经定义了三个用户变量(它们的值来自表upgrading
。在第二个语句中,我试图更新@world中包含的世界(world1
或者world2
)。在上面的示例中,它看起来像这样:@ world =' world1',@ building =' wood_max_level',@ level = 2
最后一行不正确,因为@world是一个字符串。我可以让我工作吗?
答案 0 :(得分:0)
啊,因为你的表结构不同,你可能需要做一个Pivot / unpivot。或者,你可以像这样使用case语句;
UPDATE world
SET
world.wood_max_level = case when upgrading.building = 'wood_max_level' THEN world.wood_max_level + 1 else world.wood_max_level end,
... similar for other levels ...
FROM upgrading
INNER JOIN world1
on upgrading.world = world.world_id
WHERE completion_time > 0;
在编辑你的问题后,你似乎也需要使用Dynamic Sql,因为你不知道你想要更新的表的名称,直到运行时...这是可能的,但更先进,并从您的表的架构我建议您阅读关系数据库的基础知识,并尝试重新考虑您的架构,以便在创建复杂查询之前不需要这样做。一个提示是在单个世界表中有一个WorldId列,这将消除两个具有相同模式的不同表的需要(通常是您的设计错误的标志)。在尝试构建游戏之前,我会仔细阅读数据库设计,因为在此过程中更改数据库设计要比现在更难...
答案 1 :(得分:0)
不确定这是否是您正在寻找的,我相信有一种更优雅的方式来构建它,但我认为这至少会给你一个起点示例。
我首先声明我的变量,然后检索我需要在临时表中执行更新所需的信息。我从该表中提取出我想要的各个值,以形成我可以在动态sql查询中使用的变量。我定义了我的查询,并使用sp_executesql执行,然后删除我的临时表来清理。当然,您可以将所有这些都投入到程序中。这是代码:
declare @TargetTable varchar(50);
declare @TargetColumn varchar(50);
declare @ValueToUpdate int;
select
World, Player_Id, Building, [Level]
into
#Upgrades
from
dbo.Upgrading
where
Player_Id = 2;
set @TargetTable = (
select World
from #Upgrades
);
set @TargetColumn = (
select Building
from #Upgrades
);
set @ValueToUpdate = (
select [Level]
from #Upgrades
);
declare @Query nvarchar(max);
set @Query = 'update dbo.'+@TargetTable+' set '+@TargetColumn+'='+convert(nvarchar,@ValueToUpdate)+' where Player_Id = 2';
exec sp_executesql @Query;
drop table #Upgrades;
答案 2 :(得分:0)
我找到了一个解决方案,但它并不理想。我只想执行一个查询,最后我使用了更多。它也比SQL更多PHP ...
public function checkOnBuildingQueue()
{
// SQL query and prepare the request
$sql = 'SELECT world, player_id, city_id, building, level FROM upgrading WHERE completion_time < :time;
DELETE FROM upgrading WHERE completion_time < :time;';
$query = $this->db->prepare($sql);
// prepare statements and execute query
$params = array(
'time' => time() + 2
);
$query->execute($params);
// return selected rows in array
$upgrades = $query->fetchAll();
unset($sql, $params, $query);
// $upgrade contains all finished upgrades
foreach($upgrades as $upgrade)
{
$world = $upgrade['world'];
$player_id = $upgrade['player_id'];
$city_id = $upgrade['city_id'];
$building = $upgrade['building'] . '_level';
$level = $upgrade['level'];
$sql = 'UPDATE '.$world.' SET '.$building.' = '.$level.' WHERE player_id = '.$player_id.' AND city_id = '.$city_id.'';
$query = $this->db->query($sql);
}
}