question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add the `createMany` method to SQLite

See original GitHub issue

Problem

The createMany operator is unavailable for SQLite, whilst it is available like this:

INSERT INTO `main`.`sometable` (path1, path2) VALUES
	(someValue, otherValue),
	(oneMoreValue, lastValue);

The issue is that creating hundreds of rows is extremely slow currently with usual methods, and the reason as to why Prisma exists is not writing SQL manually, but rather as an ORM.

The current solution to this problem is doing this:

const values = someArr
	.map(value => `(${value.path1}, ${value.path2})`)
	.join(",\n\t")
await prisma.$executeRawUnsafe(`INSERT INTO \`main\`.\`sometable\` (path1, path2) VALUES \n\t${values};`)

This is not ideal due to at least two reasons:

  • It uses the $queryRawUnsafe method, which can let SQL injections in - even though it’s less risky with custom validation and escaping
  • It requires custom SQL typing, which is not the goal of Prisma

Suggested solution

Add in the createMany function for SQLite, as it is working, just like for MySQL. The query can be seen above working

Alternatives

I have typed the raw SQL that makes this work above, both that work with prisma’s method and any SQL runner.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:48
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

10reactions
rafma0commented, Jul 29, 2022

From what I could find, SQLite have different limits for multiple inserts depending on the version https://stackoverflow.com/questions/15858466/limit-on-multiple-rows-insert

But for anyone looking for this only because of speeds, if you put all the inserts in the same transaction it’s MUCH faster https://sqlite.org/faq.html#q19

(19) INSERT is really slow - I can only do few dozen INSERTs per second

Actually, SQLite will easily do 50,000 or more [INSERT] statements per second on an average desktop computer. But it will only do a few dozen transactions per second. Transaction speed is limited by the rotational speed of your disk drive. A transaction normally requires two complete rotations of the disk platter, which on a 7200RPM disk drive limits you to about 60 transactions per second.
Transaction speed is limited by disk drive speed because (by default) SQLite actually waits until the data really is safely stored on the disk surface before the transaction is complete. That way, if you suddenly lose power or if your OS crashes, your data is still safe. For details, read about [atomic commit in SQLite.].

By default, each INSERT statement is its own transaction. But if you surround multiple INSERT statements with [BEGIN]...[COMMIT](https://sqlite.org/lang_transaction.html) then all the inserts are grouped into a single transaction. The time needed to commit the transaction is amortized over all the enclosed insert statements and so the time per insert statement is greatly reduced.

Another option is to run [PRAGMA synchronous=OFF]. This command will cause SQLite to not wait on data to reach the disk surface, which will make write operations appear to be much faster. But if you lose power in the middle of a transaction, your database file might go corrupt.

This can be done with something like

for (const data of datas) {
  inserts.push(prisma.post.create({ data })
}
await prisma.$transaction(inserts)

https://www.prisma.io/docs/concepts/components/prisma-client/transactions#the-transaction-api

5reactions
janpiocommented, Sep 13, 2022

That is the point of an internal discussion - sorry 😄 We dug up some historic context on how we added createMany as a preview feature, then realized it does not work for SQLite because of reasons, then removed it and blocked it - which ended up with the current state when we removed the preview feature and made it GA.

We will take that into account when we take another look at this. It is unfortunately not as trivial as it might seem from the outside with the many, many way we need to create queries under the hood.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prisma Client API (Reference)
createMany. A nested createMany query adds a new set of records to a parent record. See: Working with relations .
Read more >
sql - Is it possible to insert multiple rows at a time in an SQLite ...
update. As BrianCampbell points out here, SQLite 3.7.11 and above now supports the simpler syntax of the original post. However, the approach shown...
Read more >
SQLite Create Table with Examples
In this tutorial, you will learn how to create a new table using SQLite CREATE TABLE ... To add the table primary key...
Read more >
SQLite-Net Extensions - many-to-many relationships
It adds the extension methods/attributes to handle relationships in SQLite database. It doesn't provide any lazy-loading mechanism, instead ...
Read more >
“CREATE TABLE IF NOT EXISTS” create many TABLEs - Databases ...
Get the list of tables through the 'Tables' method right after the sql statement. This way, each time a duplicate table is added,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found