810 questions | Free
Software Engineer interview questions and answers
Most asked Software Engineer interview questions
Q1FresherMost askedPythonAnswerHideWhat is the difference between a list and a tuple in Python?
A list is mutable and a tuple is immutable. That is the core difference, and everything else follows from it.
| list | tuple | |
|---|---|---|
| Syntax | [1, 2, 3] | (1, 2, 3) |
| Mutable | Yes (append, remove, assign by index) | No |
| Hashable | No | Yes, if all items are hashable |
| Use as dict key or set member | No | Yes |
| Typical use | Homogeneous collection that changes | Fixed record, e.g. (x, y) or a function return of several values |
- Tuples are slightly smaller and faster to create, and they signal "this does not change".
- A tuple containing a list is still not fully frozen:
t = (1, [2])allowst[1].append(3). - A single-item tuple needs a comma:
(5,).
What they are checking: Whether you know mutability matters (hashing, dict keys), not just the bracket style
Q2FresherMost askedPythonAnswerHideWhat are mutable and immutable types in Python? Give examples.
A mutable object can be changed in place after creation, an immutable one cannot. Changing an immutable value really creates a new object.
- Immutable:
int,float,bool,str,tuple,frozenset,bytes. - Mutable:
list,dict,set,bytearray, and most user-defined class instances.
s = "abc"
print(id(s))
s += "d" # new string object, id changes
print(id(s))
l = [1, 2]
print(id(l))
l.append(3) # same object, id unchanged
print(id(l))
Why it matters: Mutable objects can be changed by anyone who holds them. This causes hard-to-find bugs (for example mutable default arguments). Immutable objects are safe to share and can be dict keys.
What they are checking: Understanding of object identity, and what it means for function arguments and hashing
Q3FresherMost askedPythonAnswerHideWhat is the difference between `is` and `==` in Python?
== compares values (it calls __eq__). is compares identity: do both names point to the same object in memory?
a = [1, 2]
b = [1, 2]
print(a == b) # True, equal values
print(a is b) # False, two different objects
c = a
print(c is a) # True
- Use
==for value comparison almost always. - Use
isfor singletons:x is None,x is True. - Do not use
isfor numbers or strings. CPython keeps small integers (-5 to 256) and some strings in a cache. Soismay seem to work, then fail on larger values.
What they are checking: Whether you avoid the small-integer cache trap and know to use
is None
Q4FresherMost askedPythonAnswerHideWhat are `*args` and `**kwargs`?
They let a function accept a variable number of arguments. *args collects extra positional arguments into a tuple, and **kwargs collects extra keyword arguments into a dict. The names are convention, the stars are the syntax.
def show(a, *args, **kwargs):
print(a, args, kwargs)
show(1, 2, 3, x=10, y=20) # 1 (2, 3) {'x': 10, 'y': 20}
nums = [1, 2, 3]
opts = {"sep": "-"}
print(*nums, **opts) # unpacking at the call site: 1-2-3
Order in a signature: positional parameters, *args, keyword-only parameters, **kwargs. They are common in decorators and wrappers that must forward any arguments to the wrapped function.
What they are checking: Can you use packing and unpacking, and do you know the parameter order
Q5FresherMost askedPythonAnswerHideWhat is a decorator in Python and how does it work?
A decorator is a callable that takes a function and returns a new function. It usually adds work before or after the original call. @decorator above a function is shorthand for func = decorator(func).
import functools, time
def timed(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
start = time.perf_counter()
try:
return fn(*args, **kwargs)
finally:
print(f"{fn.__name__} took {time.perf_counter() - start:.4f}s")
return wrapper
@timed
def work(n):
return sum(range(n))
work(1_000_000)
Points to mention: closures keep a reference to fn. functools.wraps preserves the name and docstring. Decorators are applied at definition time. Typical uses are logging, timing, caching, auth checks and retries.
What they are checking: Closures, first-class functions and whether you remember functools.wraps
Q6FresherMost askedPythonAnswerHideWhat are generators in Python? How is `yield` different from `return`?
A generator is a function that contains yield. Calling it returns a generator object (an iterator). It gives values lazily, one at a time. It pauses between values and keeps its local state. return ends the function for good, yield suspends it and can be resumed.
def countdown(n):
while n > 0:
yield n
n -= 1
g = countdown(3)
print(next(g)) # 3
print(list(g)) # [2, 1]
- Memory use stays small, so generators suit large or endless streams, such as reading a huge file line by line.
- A generator is exhausted after one pass. Iterating again gives nothing.
- A generator expression
(x*x for x in range(10))is the compact form.
What they are checking: Lazy evaluation and memory benefits, plus the one-pass trap
Q7FresherMost askedPythonAnswerHideWhat is the difference between shallow copy and deep copy?
A shallow copy creates a new outer container but reuses references to the inner objects. A deep copy recursively copies everything, so the result shares nothing with the original.
import copy
a = [[1, 2], [3, 4]]
s = copy.copy(a) # shallow, same as a[:] or list(a)
d = copy.deepcopy(a)
a[0].append(99)
print(s) # [[1, 2, 99], [3, 4]] inner list is shared
print(d) # [[1, 2], [3, 4]] independent
- Plain assignment
b = ais not a copy. It is a second name for the same object. - Shallow copy is fine for flat structures of immutable items.
- Deep copy is slower and handles cycles through a memo dict; classes can change it with
__deepcopy__.
What they are checking: Whether nested mutable objects are understood, not only the vocabulary
Q8ExperiencedMost askedPythonAnswerHideWhat is the GIL and how does it affect multithreading in Python?
The Global Interpreter Lock is a lock in CPython. It lets only one thread run Python bytecode at a time. It protects CPython's internal state, such as reference counts, from race conditions.
Effects:
- CPU-bound Python code gains no speed from threads, since they take turns on one core.
- I/O-bound code still benefits, because a thread releases the GIL while waiting on sockets, files or
time.sleep. - Many C extensions (NumPy, hashing, compression) release the GIL during heavy work.
- Race conditions on your own data are still possible. You still need locks for steps like
counter += 1.
Ways around it: multiprocessing or concurrent.futures.ProcessPoolExecutor for CPU-bound work, asyncio or threads for I/O, native extensions. Python 3.13 added an experimental free-threaded build (PEP 703) where the GIL can be turned off. The default build still has it.
What they are checking: Accurate detail: I/O threads work, CPU threads do not, and the GIL is not a substitute for locks
Q9ExperiencedMost askedPythonAnswerHideExplain threading vs multiprocessing vs asyncio. When would you use each?
All three give concurrency but with different models.
| threading | multiprocessing | asyncio | |
|---|---|---|---|
| Unit | OS threads, one process | Separate processes | Coroutines on one thread |
| GIL limit | Yes | No, each process has its own | Single thread anyway |
| Memory | Shared | Separate (needs pickling or shared memory) | Shared |
| Overhead | Medium | High | Very low |
| Best for | Blocking I/O with libraries that are not async | CPU-bound work | Thousands of concurrent network connections |
- Threading: preemptive switching, so races are possible and locks are needed.
- Multiprocessing: real parallelism across cores, but data moves through IPC and startup costs more.
- Asyncio: cooperative; tasks switch only at
await, so a blocking call (likerequests.get) freezes everything. Use async libraries orasyncio.to_thread.
Rule of thumb: For CPU-bound work use processes. For many network calls use asyncio. For a few blocking calls in old code use a thread pool.
What they are checking: Ability to map a workload to the right concurrency model and know the failure modes
Q10FresherMost askedPythonAnswerHideWhat are dunder (magic) methods? Explain `__str__` vs `__repr__`.
Dunder methods are special methods with double underscores. Python calls them to run built-in behaviour: __init__ (construction), __len__ (len()), __getitem__ (indexing), __eq__ (==), __add__ (+), __enter__/__exit__ (with).
__str__ is the readable, user-facing text used by print() and str(). __repr__ is clear text for developers, used in the REPL, logs and containers. It should ideally let you rebuild the object.
class P:
def __init__(self, x): self.x = x
def __repr__(self): return f"P(x={self.x!r})"
def __str__(self): return f"Point at {self.x}"
p = P(3)
print(p) # Point at 3
print([p]) # [P(x=3)] containers use repr
If only __repr__ is defined, str() falls back to it, so define __repr__ first.
What they are checking: Operator overloading awareness and the repr/str purpose
Q11FresherMost askedFree with sign-inPythonAnswerHideHow does exception handling work in Python? Explain try, except, else and finally.
Code that may fail goes in try. A matching except handles the error. else runs only if no exception happened. finally always runs, for cleanup.
Q12FresherMost askedFree with sign-inPythonAnswerHideWhat is a virtual environment in Python and why do you use one?
A virtual environment is an isolated folder with its own Python and its own installed packages. Each project keeps its own package versions. Other projects and the system Python are not affected.
Q13FresherMost askedFree with sign-inPythonAnswerHideWhat is the output of this code, and why? `def add(x, items=[]): items.append(x); return items` called as `add(1)`, `add(2)`.
It returns [1] and then [1, 2]. The default list is created once, when the function is defined, not on each call. So every call without the argument shares the same list.
Q14FresherMost askedFree with sign-inPythonAnswerHideWhat are the built-in data types in Python?
Python has these core built-in types:
- Numeric:
int(any size),float,complex, plusbool(a subclass of int). - Text:
str(immutable Unicode), and binarybytes,bytearray. - Sequences:
list,tuple,range. - Mappings:
dict. - Sets:
set,frozenset. - None:
NoneType, the single valueNone.
Q15FresherMost askedFree with sign-inPythonAnswerHideWhat does `if __name__ == '__main__':` do?
It runs a block only when the file is run directly (python script.py). It does not run when the file is imported as a module. When Python runs a file as the entry point it sets __name__ to "__main__". When imported, __name__ is the module's name.
Q16ExperiencedMost askedFree with sign-inPythonAnswerHideExplain async and await in Python. What is an event loop?
async def defines a coroutine. await pauses it until another awaitable finishes. Meanwhile the event loop runs other tasks. The event loop is the scheduler: it runs on a single thread and switches between coroutines at await points.
Q17ExperiencedMost askedScenarioFree with sign-inPythonAnswerHideA Python function is too slow in production. How do you find and fix the bottleneck?
Measure first, then optimise the part that matters.
Q18ExperiencedMost askedScenarioFree with sign-inPythonAnswerHideYou need to call 100 external APIs and combine the results. How would you do it efficiently?
This is I/O-bound. Run the calls at the same time with asyncio (or a thread pool if the client library is blocking). Also limit how many run at once.
Q19FresherMost askedJavaScriptAnswerHideWhat is the difference between var, let and const in JavaScript?
All three declare variables, but they differ in scope, hoisting and reassignment.
| var | let | const | |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Hoisted, initialised as undefined | Hoisted, but in the temporal dead zone until declared | Same as let |
| Redeclare in same scope | Allowed | Error | Error |
| Reassign | Yes | Yes | No |
conststops reassignment of the binding, not mutation of the value:const a = []; a.push(1)works.- Prefer
constby default,letwhen you must reassign, and avoidvarin new code. - A
vardeclared at the top level of a script becomes a property of the global object;letandconstdo not.
What they are checking: Whether you understand scope and the temporal dead zone, not only the table
Q20FresherMost askedJavaScriptAnswerHideWhat is hoisting in JavaScript?
Hoisting means declarations are processed before the code runs. So names are known in their scope before the line that declares them.
varis hoisted and initialised withundefined, so reading it early givesundefined.letandconstare hoisted but not initialised. Accessing them before the declaration throws aReferenceError(the temporal dead zone).- Function declarations are hoisted with their body, so you can call them before they appear.
- Function expressions and arrow functions follow the rule of the variable that holds them.
console.log(a); // undefined
var a = 1;
sayHi(); // works
function sayHi() { console.log("hi"); }
console.log(b); // ReferenceError
let b = 2;
What they are checking: Whether you know the difference between var, let and function hoisting
Q21FresherMost askedJavaScriptAnswerHideWhat is a closure? Give a practical example.
A closure is a function together with the variables from the scope where it was created. The function keeps access to those variables even after the outer function has returned.
function makeCounter() {
let count = 0;
return () => ++count;
}
const next = makeCounter();
next(); // 1
next(); // 2
count is private: nothing outside can change it except through the returned function.
Common uses: data privacy, function factories, partial application, memoisation, and event handlers or callbacks that remember state. A common trap is capturing a loop variable declared with var. Also, a closure that holds a large object can keep it in memory longer than you expect.
What they are checking: Whether you can explain it simply and name real uses
Q22FresherMost askedJavaScriptAnswerHideHow does the this keyword work in JavaScript?
this is decided by how a function is called, not where it is written. Arrow functions are the exception.
- Method call
obj.fn():thisisobj. - Plain call
fn():thisisundefinedin strict mode and modules, the global object in sloppy mode. new Fn():thisis the new object.call,apply,bind: you setthisyourself.- Arrow functions have no own
this; they use the one from the enclosing scope. - In a DOM event handler (regular function),
thisis the element.
const user = { name: "Asha", hi() { return this.name; } };
user.hi(); // "Asha"
const f = user.hi;
f(); // this lost: undefined or error in strict mode
What they are checking: Whether you can predict this from the call site
Q23FresherMost askedJavaScriptAnswerHideWhat is the difference between call, apply and bind?
All three set this for a function. They differ in when the function runs and how arguments are passed.
fn.call(thisArg, a, b): runs now, arguments listed one by one.fn.apply(thisArg, [a, b]): runs now, arguments as an array.fn.bind(thisArg, a): does not run; returns a new function withthis(and optionally leading arguments) fixed.
function intro(city, country) { return `${this.name}, ${city}, ${country}`; }
const p = { name: "Sita" };
intro.call(p, "Pokhara", "Nepal");
intro.apply(p, ["Pokhara", "Nepal"]);
const bound = intro.bind(p, "Pokhara");
bound("Nepal");
A bound function cannot be re-bound to a different this.
What they are checking: Whether you know each one's timing and argument style
Q24FresherMost askedJavaScriptAnswerHideWhat is the difference between == and === in JavaScript?
=== (strict equality) compares value and type with no conversion. == (loose equality) first converts both sides to a common type. This gives unexpected results.
0 == "0" // true
0 === "0" // false
null == undefined // true
null === undefined // false
NaN === NaN // false
[] == false // true
Use === by default. The one accepted use of == is value == null to test for both null and undefined. For NaN use Number.isNaN, and Object.is treats NaN as equal to itself and distinguishes +0 from -0.
What they are checking: Whether you know type coercion and default to strict equality
Q25ExperiencedMost askedJavaScriptAnswerHideExplain the JavaScript event loop.
JavaScript runs your code on one thread. The event loop is what lets it handle async work without blocking.
- Synchronous code runs on the call stack until it is empty.
- The host (browser or Node) handles async APIs (timers, network, DOM events). Later it queues a callback.
- Promise reactions and
queueMicrotaskcallbacks go to the microtask queue. Timers and I/O callbacks go to the macrotask (task) queue. - When the stack is empty, the loop runs all microtasks. Then it takes one macrotask and runs it. Then it runs microtasks again, and repeats. In browsers rendering happens between tasks.
What this means: a long synchronous loop freezes the page and delays timers. setTimeout(fn, 0) means "after the current code and microtasks". A microtask that keeps adding microtasks can block rendering.
What they are checking: Whether you can describe stack, queues and ordering, not only say single threaded
Q26FresherMost askedJavaScriptAnswerHideWhat is the output of this loop, and how do you fix it?
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); }
It prints 3 3 3.
var is function scoped, so there is one shared i. The timeout callbacks run after the loop ends, when i is already 3.
Fixes:
// 1. let creates a new binding per iteration
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i), 0); // 0 1 2
// 2. IIFE capturing the value
for (var i = 0; i < 3; i++) {
((j) => setTimeout(() => console.log(j), 0))(i);
}
This is the classic closure-in-loop question. The key point is that closures capture variables, not values.
What they are checking: Whether you connect closures and scope to a real bug
Q27ExperiencedMost askedJavaScriptAnswerHideWhat is the output of this code, and why?
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
Output: 1 4 3 2.
1and4are synchronous, so they run first in order.- The promise callback is a microtask, so it runs as soon as the stack is empty:
3. setTimeoutis a macrotask, so it runs after the microtasks:2, even with a delay of 0.
A harder variant adds async function f() { console.log('a'); await null; console.log('b'); }. Code before the first await runs synchronously; the code after it is a microtask. Explain by naming the stack, microtask queue and task queue.
What they are checking: Whether you can trace event loop ordering
Q28FresherMost askedSQLAnswerHideWhat are the different types of SQL joins? Explain with an example.
A join combines rows from two tables on a related column. Take two tables:
employees(id, name, dept_id) and departments(id, dept_name).
| Join | Returns |
|---|---|
| INNER JOIN | Only rows that match in both tables |
| LEFT JOIN | All rows from the left table, NULL where the right has no match |
| RIGHT JOIN | All rows from the right table, NULL where the left has no match |
| FULL OUTER JOIN | All rows from both (PostgreSQL yes, MySQL has no direct support) |
| CROSS JOIN | Every combination (cartesian product) |
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON d.id = e.dept_id;
This lists every employee, and dept_name is NULL for an employee with no department. With INNER JOIN that employee would disappear. A self join joins a table to itself, for example to find an employee's manager.
What they are checking: Whether you know what happens to unmatched rows, not just the names
Q29FresherMost askedSQLAnswerHideWhat is the difference between WHERE and HAVING?
WHERE filters individual rows before grouping. HAVING filters groups after GROUP BY and can use aggregate functions.
SELECT dept_id, COUNT(*) AS headcount, AVG(salary) AS avg_salary
FROM employees
WHERE salary > 20000 -- row filter, runs first
GROUP BY dept_id
HAVING COUNT(*) > 5; -- group filter, runs after aggregation
- WHERE cannot contain aggregates such as
COUNT(*)orAVG(). - Put conditions in WHERE whenever possible, because it reduces rows before grouping and is faster.
- Logical order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT.
What they are checking: Understanding of SQL's logical execution order
Q30FresherMost askedSQLAnswerHideWhat is the difference between a primary key and a foreign key?
A primary key uniquely identifies each row in its own table. A foreign key is a column that points to the primary key of another table. It enforces the link between them.
| Primary key | Foreign key | |
|---|---|---|
| Purpose | Identify a row | Link to a row in another table |
| NULLs | Not allowed | Allowed (unless declared NOT NULL) |
| Duplicates | Not allowed | Allowed |
| Per table | Exactly one (can be composite) | Many |
CREATE TABLE departments (id INT PRIMARY KEY, name VARCHAR(50));
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
The foreign key blocks adding an employee with a department that does not exist. It also controls what happens on delete (ON DELETE CASCADE, SET NULL, or restrict).
What they are checking: Referential integrity basics
Q31FresherMost askedSQLAnswerHideWhat is the difference between DELETE, TRUNCATE and DROP?
DELETE removes selected rows, TRUNCATE empties the whole table, DROP removes the table itself.
| DELETE | TRUNCATE | DROP | |
|---|---|---|---|
| Type | DML | DDL | DDL |
| WHERE clause | Yes | No | No |
| Removes | Chosen rows | All rows | Table and structure |
| Triggers fire | Yes | No | No |
| Speed | Slower (row by row, logged) | Fast | Fast |
| Rollback | Yes | PostgreSQL yes (inside a transaction), MySQL no (implicit commit) | MySQL no, PostgreSQL yes in a transaction |
DELETE FROM orders WHERE status = 'cancelled';
TRUNCATE TABLE temp_logs;
DROP TABLE temp_logs;
TRUNCATE also resets auto-increment counters in MySQL.
What they are checking: DML vs DDL and the side effects
Q32FresherMost askedSQLAnswerHideHow do you find the Nth highest salary in SQL?
Use DENSE_RANK so ties are handled correctly, or LIMIT with OFFSET on distinct values.
-- 3rd highest salary (change 3 to N)
SELECT salary
FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) t
WHERE rnk = 3
LIMIT 1;
Alternative without window functions:
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 2; -- OFFSET is N - 1
ROW_NUMBERwould count tied salaries as separate ranks, which is wrong here.RANKleaves gaps after ties, so the 3rd rank may not exist.- If fewer than N distinct salaries exist, both queries return no row.
What they are checking: Handling of ties and knowing rank functions
Q33FresherMost askedSQLAnswerHideHow do you find the highest salary in each department (max per group)?
Group by department to get just the value. Or join back, or use a window function, to get the full row.
-- Only the max value
SELECT dept_id, MAX(salary) AS max_salary
FROM employees
GROUP BY dept_id;
-- Whole row of the top earner (ties return all)
SELECT e.*
FROM employees e
JOIN (
SELECT dept_id, MAX(salary) AS max_salary
FROM employees
GROUP BY dept_id
) m ON m.dept_id = e.dept_id AND m.max_salary = e.salary;
-- Same with a window function
SELECT * FROM (
SELECT e.*, RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rnk
FROM employees e
) t WHERE rnk = 1;
The common mistake is selecting name together with MAX(salary) in a GROUP BY query. Name is not aggregated, so PostgreSQL rejects it and MySQL with ONLY_FULL_GROUP_BY does too.
What they are checking: The classic 'greatest-n-per-group' pattern
Q34FresherMost askedSQLAnswerHideHow do you delete duplicate rows from a table while keeping one copy?
Keep the row with the smallest id for each duplicate key and delete the rest.
DELETE FROM contacts
WHERE id NOT IN (
SELECT min_id FROM (
SELECT MIN(id) AS min_id
FROM contacts
GROUP BY email
) keep
);
The extra derived table (keep) is needed in MySQL. MySQL refuses to read and delete from the same table in one subquery. It also works in PostgreSQL.
First find duplicates to verify:
SELECT email, COUNT(*) FROM contacts GROUP BY email HAVING COUNT(*) > 1;
Run it inside a transaction or on a backup first. To prevent the problem permanently, add ALTER TABLE contacts ADD CONSTRAINT uq_email UNIQUE (email);.
What they are checking: Safe data cleanup and prevention
Q35ExperiencedMost askedSQLAnswerHideWhat is a window function? Explain ROW_NUMBER, RANK and DENSE_RANK.
A window function computes a value across a set of rows related to the current row. Unlike GROUP BY, it does not collapse them. You define the set with OVER (PARTITION BY ... ORDER BY ...).
For salaries 90, 80, 80, 70 ordered descending:
| Salary | ROW_NUMBER | RANK | DENSE_RANK |
|---|---|---|---|
| 90 | 1 | 1 | 1 |
| 80 | 2 | 2 | 2 |
| 80 | 3 | 2 | 2 |
| 70 | 4 | 4 | 3 |
- ROW_NUMBER: unique sequence, ties broken arbitrarily.
- RANK: ties share a rank, then a gap.
- DENSE_RANK: ties share a rank, no gap.
SELECT name, dept_id, salary,
RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dept_rank
FROM employees;
Other common ones: LAG, LEAD, SUM() OVER, NTILE, FIRST_VALUE.
What they are checking: Whether you know analytics SQL beyond GROUP BY
Q36FresherMost askedSQLAnswerHideWhat is an index and how does it speed up queries? What is the downside?
An index is a separate sorted structure (usually a B-tree). It lets the database find rows without scanning the whole table, like a book index.
CREATE INDEX idx_orders_customer ON orders (customer_id);
Benefits: fast lookups, joins, sorting and range queries on the indexed column.
Costs:
- Extra disk space.
- Slower INSERT, UPDATE and DELETE, since every index must be maintained.
- Too many indexes confuse the planner and waste memory.
Good candidates are columns used in WHERE, JOIN, ORDER BY and foreign keys with high selectivity. Poor candidates are tiny tables and low-cardinality columns such as a boolean. A composite index (a, b) helps queries that filter on a, or on a and b. It does not help a filter on b alone (leftmost prefix rule).
What they are checking: Costs and benefits, not just definitions
Q37FresherMost askedSQLAnswerHideExplain ACID properties with an example.
ACID is the set of guarantees of a database transaction.
- Atomicity: all steps happen or none do.
- Consistency: a transaction moves the database from one valid state to another, respecting constraints.
- Isolation: concurrent transactions do not see each other's half-finished work.
- Durability: once committed, data survives a crash (through the write-ahead log).
Example, transferring 500 from account A to B:
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
If the second update fails, ROLLBACK restores the first, so money never disappears (atomicity). Constraints such as balance >= 0 keep it consistent. Another session reading mid-transfer does not see a partial state (isolation). After COMMIT a power cut does not lose it (durability).
What they are checking: Concepts tied to a concrete example
Q38FresherMost askedFree with sign-inSQLAnswerHideExplain normalization and the first three normal forms.
Normalization organizes tables to reduce redundancy and update anomalies.
Q39ExperiencedMost askedFree with sign-inSQLAnswerHideWhat are the transaction isolation levels and what problems does each prevent?
Isolation levels trade consistency for concurrency. The problems they prevent:
- Dirty read: reading uncommitted data of another transaction.
- Non-repeatable read: the same row read twice returns different values.
- Phantom read: the same query returns new rows the second time.
Q40ExperiencedMost askedScenarioFree with sign-inSQLAnswerHideHow would you get the top 3 highest-paid employees in every department?
Rank within each department using a window function, then filter.