-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update statements with joins don't seem to work #192
Comments
Hey, The You can use a subquery for now.. something like this should work: db.updateTable('OverallMV as O1')
.set({ Tied: 1 })
.whereExists((eb) =>
eb
.selectFrom('OverallMV as O2')
.whereRef('O1.Rank', '=', 'O2.Rank')
.whereRef('O1.UserID', '<>', 'O2.UserID')
.select(['O2.Rank', 'O2.UserId'])
)
.execute() Let me know if that did the trick for you.. |
@igalklebanov Unfortunately that won't work. Using what you wrote gives the following error:
Doing a quick search on SO says to use inner join to fix: https://stackoverflow.com/a/45498 There is a possibility to try to nest the where exists deeper which I will try in a bit but would love to have the update join option. |
Damn, how about a |
This would only work on MySQL AFAIK, so I haven't supported that syntax. |
Yeah, MySQL has that weird limitation. This should work: db.updateTable('OverallMV as O1')
.set({ Tied: 1 })
.whereExists((eb) =>
eb.selectFrom((eb) => eb
.selectFrom('OverallMV as O2')
.whereRef('O1.Rank', '=', 'O2.Rank')
.whereRef('O1.UserID', '<>', 'O2.UserID')
.select(['O2.Rank', 'O2.UserId'])
.as('O3')
).selectAll('O3')
)
.execute() |
@igalklebanov This doesn't work since the |
@koskimas I hear you, however, part of why I love Kysely so far and am trying to convince my team to convert is its simplicity in doing SQL operations. Your blog post calls out how it implements things that might not be available on the specific DB you are working on in the section on
The workaround you posted I was also able to generate yesterday to work, however, it is very ugly and difficult to understand what is happening for devs reading this code: await trx.updateTable("OverallMV as O").set({ Tied: 1 }).whereExists((qb) =>
qb.selectFrom((qb) =>
qb.selectFrom("OverallMV as O2")
.select([sql.literal(1).as("Found")])
.whereRef("O.Rank", "=", "O2.Rank")
.whereRef("O.UserID", "<>", "O2.UserID").as("INNER")
).select("INNER.Found")
).execute(); I would hope that updates with joins is something that is considered to be supported as it is not uncommon on MySQL due to not being able to use where exists over the same table being updated. Thanks for your help in the meantime, I appreciate the quick response! |
It's ok to add custom methods that don't exist on other dialects. People don't call them accidentally (well at least not as easily). But the |
I think what @igalklebanov suggested regarding trx
.with('someGoodName', (qb) => qb
.selectFrom("OverallMV as O")
.innerJoin("OverallMV as O2", (join) => join
.onRef("O.Rank", "=", "O2.Rank")
.onRef("O.UserID", "<>", "O2.UserID")
)
.select('ID')
)
.updateTable("OverallMV")
.whereExists((eb) => eb.selectFrom("someGoodName").select("ID"))
.set({ Tied: 1 }) |
I'll definitely consider supporting joins like you suggested (and I have considered it), but it can be very difficult because of the other way of using joins in update statements (in a |
@koskimas following Kysely's philosophy of what you invoke is what you get... we could simply support this by checking if consumer invoked Wdyt? |
That wouldn't work with the types. Correct me if I'm wrong, but on MySQL you can update all joined tables? So we would need to append to |
You're right. Types are too complicated and its surprising to consumers ( I think expanding
db.updateTable(['person', 'pet'])
.set({
'person.status': 'Cat lady',
'pet.owner_id': uuid,
})
.where('person.id', '=', uuid)
.where('pet.owner_id', 'is', null)
.where('pet.species', '=', 'cat')
.execute()
db.updateTable('person', (jb) => jb.innerJoin('pet', 'pet.owner_id', 'person.id'))
.set({
'person.status': 'Proud dog parent',
'pet.status': 'Happy pup',
})
.where('pet.species', '=', 'dog')
.execute() Would be aligned with consumer's expectations of affecting the query's main clause, and will make "downstream" types consistent and simpler. |
Very surprising that this doesn't work but I get the complications, Typescript can be a curse sometimes 😅 Any updates on @igalklebanov's suggestion? db.updateTable('person', (jb) => jb.innerJoin('pet', 'pet.owner_id', 'person.id')) and think this looks like a good option 👍🏼 Would be amazing if this could be considered if it works like that. |
+1 for @igalklebanov 's suggestion to support an array of table references:
|
This comment was marked as spam.
This comment was marked as spam.
I'm finally adding support for |
Hello! Just switched from Prisma and loving the library so far. Just ran into an issue where I'm hoping there's a workaround or I'm doing something wrong.
Basically, I have an existing MySQL statement that reads:
So I recreated it in Kysely as:
However, this fails with a
ER_PARSE_ERROR
since it puts the set before the join:Any ideas here?
Side note, I'm wondering if this use case was never tested as I would also expect to choose which table to update in the set. So more like
.set({ "O.Tied": 1 })
, which does not currently work but.set({ Tied: 1 })
does.The text was updated successfully, but these errors were encountered: