Is this the correct way to use With clause (CTEs) to delete a row using only one transaction?
export const deleteMainAccountUser = async (publicUserId: string, publicMainAccountId: string) => {
const userId = neonClient
.$with('user_id')
.as(neonClient.select({ id: user.id }).from(user).where(eq(user.publicUserId, publicUserId)))
const mainAccountId = neonClient
.$with('account_id')
.as(
neonClient
.select({ id: mainAccount.id })
.from(mainAccount)
.where(eq(mainAccount.publicId, publicMainAccountId))
)
return neonClient
.with(userId, mainAccountId)
.delete(mainAccountUser)
.where(
and(eq(mainAccountUser.userId, userId), eq(mainAccountUser.mainAccountId, mainAccountId))
)
}
I first need to get both the userId and mainAccountId before removing the row in mainAccountUser, is this the best way to do it? Do I have to use sql in order to fully use the CTEs flow?8 Replies
Using WITH/AS does not return a value (like userId). It returns a query. Your code should look more like this:
The resulting query would look like this:
Here's an example from the docs:
https://orm.drizzle.team/docs/delete#with-delete-clause
Drizzle ORM - Delete
Drizzle ORM is a lightweight and performant TypeScript ORM with developer experience in mind.
Oh, it returns a query, so I'm actually running multiple queries from a single query, that makes sense 🙂 I wish there were more examples like this for these options in the docs especially when it's a more advanced option.
Thank you very much for the help
Why do you need to run "SELECT * FROM" instead of just running the query: sql
(${userId})
?Because you're using WITH/AS. Here's an example with my db. In the WHERE clause, you're referencing the WITH id as a sort of pseudo table name.
vs
I believe the alternative approach would look like this:
Oh, the alternative looks much more friendly, it should work the same?
You didn't use the .with() on the return query, why?
You don't need it when not using
WITH/AS
. You're encoding the entire query in the WHERE, rather than the WITH id.And it has the same performance as with the first option (with/as)? How can I test how many transactions are running per query?
As far as I know they have the same performance.
The advantage of WITH/AS is not having to repeat a subquery. If you have to repeat a subquery, then there may be a performance benefit, but the query optimizer is usually pretty good about it.
For example, this contrived example:
could be refactored to:
ok I see now, thank you for the explanations and examples 👏