executeRaw could support multiple queries from a single string
See original GitHub issueProblem
Since prisma migrate
is experimental and our team is waiting for #446, I was trying to create a simple migration tool. Our needs aren’t big for now so a simple script would help.
I made a node script that would read .sql
files from a scripts
folder and run them sequentially:
import { PrismaClient } from '@prisma/client';
import path from 'path';
import fs from 'fs';
const main = async () => {
const db = new PrismaClient();
try {
// Create the migrations table
await db.executeRaw(
'CREATE TABLE IF NOT EXISTS `Migrations` (`id` int NOT NULL AUTO_INCREMENT, `executedAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `migrationName` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `Migrations.migrationName` (`migrationName`));'
);
// Read all the sql scrips
const basePath = path.join(__dirname, './scripts');
const scripts = fs.readdirSync(basePath, { encoding: 'utf8' });
// For each file
for (const fileName of scripts) {
// We have to wrap empty results with try catch. Waiting for https://github.com/prisma/prisma/issues/2867
try {
// Check if the migration ran already
await db.queryRaw`SELECT 1 FROM Migrations WHERE migrationName = '${fileName}' LIMIT 1`;
} catch {
// If didn't
// Get the sql content
const sql = fs.readFileSync(path.join(basePath, fileName), {
encoding: 'utf8'
});
// Run the sql
await db.executeRaw(sql);
// Update the migration table
await db.executeRaw`INSERT INTO Migrations(migrationName) VALUES ('${fileName}')`;
}
}
} catch (error) {
console.error(error);
} finally {
await db.disconnect();
}
};
main().catch((e) => console.error(e));
But every time when executing the script, which has multiple queries like CREATE TABLE
or ALTER TABLE
, executeRaw
throws an error:
PrismaClientKnownRequestError: Raw query failed. Code: `1064`. Message: `You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE IF NOT EXISTS `MyTable` (
`id` int NOT NULL AUTO_INCREMEN' at line 31`
at PrismaClientFetcher.request (D:\dev\perimetre\export-connect-backend\node_modules\@prisma\client\src\runtime\getPrismaClient.ts:902:15)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
code: 'P2010',
meta: {
code: '1064',
message: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE IF NOT EXISTS `IndustrySector` (\r\n" +
" `id` int NOT NULL AUTO_INCREMEN' at line 31"
}
}
The script is not incorrect as it runs fine with Mysql Workbench. And if I take only one query from the script and make a file with only that. It also runs fine.
Suggested solution
db.executeRaw
could support running multiple queries instead of only one
Issue Analytics
- State:
- Created 3 years ago
- Reactions:11
- Comments:14 (3 by maintainers)
Top Results From Across the Web
Raw database access (Reference) - Prisma
$executeRaw does not support multiple queries in a single string (for example, ALTER TABLE and CREATE TABLE together). Prisma Client submits prepared ...
Read more >How can execute multiple statements in one query with Rails?
From the MySQL/PHP docs: CLIENT_MULTI_STATEMENTS: Tell the server that the client may send multiple statements in a single string (separated by ...
Read more >SQL Queries - EF Core - Microsoft Learn
SQL queries can return regular entity types or keyless entity types ... it can be useful to use named parameters in the SQL...
Read more >Execute Raw SQL Query in Entity Framework 6
Use the DbSet.SqlQuery() method to write raw SQL queries which return entity instances. The resulted entities will be tracked by the context, as...
Read more >Executing Raw SQL Queries using Entity Framework Core
Entity Framework Core will only parameterize format strings if they are ... Support for returning ad hoc (not DbSet ) types from direct...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
executeRawUnsafe
will not execute multiple queries andupdateMany
is only for updating lots of records for the same value. But if you want to update many records with specific values per record there is not a good pattern for that. It turns out if you are only updating a single field on each record then there is a fun pattern:I wrote a small function that helps build this (and chunk into 10000 records at a time so the query isn’t longer than 4mb):
To use it I set the field value on a set of records I’ve fetched then
Edit: this is
chunkArray
:🚨 Note: the
ELSE
is critical here. ThisUPDATE
covers every row in the table when it runs… but for the non enumerated cases it resolves tofieldname = fieldname
which is a noop for the database. That is fine if your absolute set is not wildly large (and will generally be optimized out). However, if you need to restrict it, you should add aWHERE ID IN ()
statement that limits theUPDATE
to the covered set of IDs.Two years later and no progress on something so rudimentary?
In my case the need arises due to another missing API. updateMany doesn’t support multiple updates with different where cases. An example would be:
I cannot do:
neither can I do:
The working alternative with Promise.all and single update exhausts the connection pool, while sequential run is extremely slow for large number of rows.