NestJs MySQL : Execute Raw SQL Queries


NestJS में MySQL के साथ raw SQL queries run करना तब काम आता है जब आपको complex SQL queries execute करनी हूँ जो आपके ORM (Object Relational Mapping) से efficiently handle नहीं हो पा रही हो।

TypeORM जो एक ORM है, generally आपको abstraction provide करता है ताकि आप SQL queries को object-oriented तरीके से लिख सकें, लेकिन कभी-कभी आपको direct raw SQL queries लिखने कि need होती है, especially जब आपको complex joins, performance tuning, या non-standard SQL operations perform करनी हो।

इस topic में हम देखेंगे कि कैसे NestJS में MySQL के साथ raw SQL queries run करते हैं using TypeORM, और इसके फायदे और methods को detail में समझेंगे।

NestJs MySQL Raw Queries

Raw queries का use तब करना चाहिए जब -

  • Complex Queries : आपको ऐसी complex queries लिखनी हो जो ORM easily handle नहीं कर सकता, जैसे multi-table joins या custom aggregation queries.

  • Performance Optimizations : अगर आपको query performance को optimize करना हो तो raw SQL queries का use करना better होता है।

  • Database-Specific Functions : जैसे triggers, stored procedures, या ऐसे database-specific operations जो ORM support नहीं करता।

NestJs MySQL Setup Configuration

make sure , आपने mysql2 package install कर लिया है अपने project में।

File : src/app.module.ts

import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserModule } from './user/user.module'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'nest_db', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, // Development ke liye synchronize true rakhein }), UserModule, ], }) export class AppModule {}

Create Database Helper Class

चलिए अब हम एक SQLHelper class बनाते हैं जो raw queries को run करेगी। इस class में हम एक generic method runQuery() बनाएंगे जो SQL query को execute करेगा।

File : src/common/sql.helper.ts

import { Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; @Injectable() export class SQLHelper { constructor(private dataSource: DataSource) {} // Generic function to run any raw SQL query async runQuery(query: string, parameters?: any[]): Promise<any> { try { const result = await this.dataSource.query(query, parameters || []); return result; } catch (error) { console.error('Error executing query:', error); throw new Error('Database query failed'); } } }

यहां

  • runQuery(query: string, parameters?: any[]) एक generic function है जो किसी भी SQL query को execute करेगा।

  • parameters एक optional array है जो query के dynamic values को inject करने के लिए use होता है (ताकि SQL injection से बच सकें).

  • try-catch block का use करके errors को handle किया गया है।

NestJs MySQL Example

अब जब हमने SQLHelper class बनाली है, तो हम इस class का use करके अलग-अलग SQL queries को run कर सकते हैं बिना हर बार services लिखे।

चलिए अब हम UserService को हटा कर directly SQLHelper का use किसी controller या किसी दूसरी service में कर करते हैं।

File : src/user/user.controller.ts

import { Controller, Get, Post, Param, Body } from '@nestjs/common'; import { SQLHelper } from '../common/sql.helper'; @Controller('users') export class UserController { constructor(private readonly sqlHelper: SQLHelper) {} // GET all users using SQLHelper @Get() async getAllUsers() { const query = 'SELECT * FROM users'; return this.sqlHelper.runQuery(query); } // GET user by ID using SQLHelper @Get(':id') async getUserById(@Param('id') id: number) { const query = 'SELECT * FROM users WHERE id = ?'; return this.sqlHelper.runQuery(query, [id]); } // POST: Insert new user using SQLHelper @Post() async insertUser(@Body() userData: { name: string; email: string; age: number }) { const query = 'INSERT INTO users (name, email, age) VALUES (?, ?, ?)'; return this.sqlHelper.runQuery(query, [userData.name, userData.email, userData.age]); } }

Example में हमने SQLHelper का use करके queries run की हैं जो centralized query execution को handle करती है। getAllUsers(), getUserById(), और insertUser() methods ने directly runQuery() को call किया है।

इस तरीके से आप सभी SQL operations को एक जगह से manage कर सकते हैं, जो code को simple और clean रखता है।

NestJs MySQL Dynamic Searching

Helper class का use real-world scenarios में काफी फायदेमंद होता है जब आपको multiple services में similar queries लिखनी होती हैं या आपको queries को dynamically create करना होता है।

अब हम एक example देखते हैं जिसमे dynamic filtering और sorting को SQLHelper के साथ implement करते हैं।

File : src/user/user.controller.ts

import { Controller, Get, Query } from '@nestjs/common'; import { SQLHelper } from '../common/sql.helper'; @Controller('users') export class UserController { constructor(private readonly sqlHelper: SQLHelper) {} // GET users with optional filters and sorting @Get('search') async searchUsers( @Query('name') name?: string, @Query('age') age?: number, @Query('sort') sort?: string ) { let query = 'SELECT * FROM users WHERE 1=1'; const parameters = []; if (name) { query += ' AND name LIKE ?'; parameters.push(`%${name}%`); } if (age) { query += ' AND age = ?'; parameters.push(age); } if (sort) { query += ` ORDER BY ${sort}`; } return this.sqlHelper.runQuery(query, parameters); } }

यहां

  • Dynamic filtering (name, age) और sorting को handle करने के लिए query को dynamically construct किया गया है।

  • SQLHelper के through query run कि गयी है और results को return किया गया है।

What does query() return ?

जब आप NestJS में this.dataSource.query() function का use करते हैं तो raw SQL queries run करने के लिए, यह function Promise return करता है जो query के execution का result return करता है।

1. For SELECT Queries :

जब आप SELECT query run करते हैं, तो यह function एक array of objects return करता है, जिसमें हर object एक row (record) को represent करता है।

हर row का data key:value pair के form में होता है, जिसमें keys आपके table के column names होते हैं, और values वो specific record के values होते हैं।

For example

const users = await this.dataSource.query('SELECT * FROM users'); console.log(users);

Output

[
  { "id": 1, "name": "John", "email": "john@example.com", "age": 30 },
  { "id": 2, "name": "Jane", "email": "jane@example.com", "age": 25 }
]

2. For INSERT, UPDATE, and DELETE Queries

जब आप INSERT, UPDATE, या DELETE queries run करते हैं, तो this.dataSource.query() function query के execution का metadata return करता है, जो query का status, affected rows, etc. को represent करता है।

Example

const result = await this.dataSource.query( 'INSERT INTO users (name, email, age) VALUES (?, ?, ?)', ['Alice', 'alice@example.com', 28] ); console.log(result);

Output

{
  "fieldCount": 0,
  "affectedRows": 1,
  "insertId": 3,   // ID of the newly inserted row
  "serverStatus": 2,
  "warningCount": 0,
  "message": "",
  "protocol41": true,
  "changedRows": 0
}

NestJs MySQL Best Practices

  • Centralized Query Execution : एक helper class का use करना एक smart approach है जो raw SQL queries को centralize करता है। यह आपको code re-usability और maintainability में help करता है।

  • Error Handling : हर query के execution के साथ error handling जरूर लगाएं। अगर कोई query fail होती है तो proper logging और error messages दिखाने का ध्यान रखें।

  • Use Parameterized Queries : Parameterized queries का use करना SQL injection attacks से बचने का best तरीका है. हर dynamic value को parameterize करें ताकि query safe हो।

  • Optimize Complex Queries : जब complex SQL queries लिख रहे हो, तो ensure करें कि queries optimized हूँ. Indexing और query execution plans का ध्यान रखें।

  • Modular Structure : SQLHelper को modular और independent रखें ताकि आप इससे easily reuse कर सकें across multiple modules और services.

Hey ! I'm Rahul founder of learnhindituts.com. Working in IT industry more than 4.5 years. I love to talk about programming as well as writing technical tutorials and blogs that can help to others .... keep learning :)

Get connected with me - LinkedIn Twitter Instagram Facebook