Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

Tuesday, May 28, 2019

SQL SERVER – Insert Multiple Records Using One Insert Statement



How can we insert multiple values in table using only one insert? 
When there are multiple records are to be inserted in the table following is the common way using T-SQL.
 

INSERT INTO MyTable  (FirstCol, SecondCol)
        VALUES ('First',1);
INSERT INTO MyTable  (FirstCol, SecondCol)
        VALUES ('Second',2);
INSERT INTO MyTable  (FirstCol, SecondCol)
        VALUES ('Third',3);
INSERT INTO MyTable  (FirstCol, SecondCol)
        VALUES ('Fourth',4);
INSERT INTO MyTable  (FirstCol, SecondCol)
        VALUES ('Fifth',5);
GO

The clause INSERT INTO is repeated multiple times. Many times DBA copy and paste it to save time. There is another alternative to this, using UNION ALL and INSERT INTO … SELECT… clauses. 
Regarding performance there is not much difference. Also, insert script is used one time, so performance does not make much difference.

INSERT INTO MyTable (FirstCol, SecondCol)
SELECT 'First' ,1
UNION ALL
SELECT 'Second' ,2
UNION ALL
SELECT 'Third' ,3
UNION ALL
SELECT 'Fourth' ,4
UNION ALL
SELECT 'Fifth' ,5
GO

The effective result is same.

If one is using SQL Server 2008, then a new feature to insert multiple rows in SQL with using only one SELECT statement can be used.

SQL Server 2008 Method of Row Construction:
 

INSERT INTO MyTable (FirstCol, SecondCol)
VALUES ('First',1),
('Second',2),
('Third',3),
('Fourth',4),
('Fifth',5)

Thursday, January 11, 2018

What is syspolicy_purge_history


This job is created by default when an instance of SQL Server 2008 is installed or upgraded to SQL Server 2008.



SQL Server 2008 introduced a new feature called Policy Based Management. A Policy can be something like xp_cmdshell should not be enabled on an instance. When a policy runs it stores the results in MSDB. Over a period of time, this may will cause unnecessary data getting piled up in MSDB. The job syspolicy_purge_history prunes the data older than the the days defined in HistoryRetentionInDays property of Policy Management.

In the above screenshot it is set to 0 which means that the Policy Evaluation History will never be deleted. So on this instance the job is running just like that 
If this job is missing for some reason, it can always be recreated using the below query
EXEC msdb.dbo.sp_syspolicy_create_purge_job

Friday, August 28, 2015

How To Resolve Database Blocking In Oracle

Database blocking is a situation where the statement run by one user locks a record or set of records and another statement run by the same user or different user requires a conflicting lock type on the record or records, locked by the first user.

Database blocking issue is a very common scenario in any application.

How to Identify the blocking session
1. DBA_BLOCKERS  : Gives information only about the blocking session.
SQL> select * from dba_blockers;
HOLDING_SESSION
—————
252
 
2. v$LOCK  : Gives details of blocking and waiting session.
SQL> select l1.sid, ‘ IS BLOCKING ‘, l2.sid
from v$lock l1, v$lock l2
where l1.block =1 and l2.request > 0
and l1.id1=l2.id1
and l1.id2=l2.id2
/
SID ‘ISBLOCKING’         SID
———- ————- ———-
244  IS BLOCKING         252
 
To get more specific details use the below query:
 
SQL> select s1.username || ‘@’ || s1.machine
|| ‘ ( SID=’ || s1.sid || ‘ )  is blocking ‘
|| s2.username ||
‘@’|| s2.machine || ‘ ( SID=’ || s2.sid || ‘ ) ‘ AS blocking_status
from v$lock l1, v$session s1, v$lock l2, v$session s2
where s1.sid=l1.sid and s2.sid=l2.sid
and l1.BLOCK=1 and l2.request > 0
and l1.id1 = l2.id1
and l2.id2 = l2.id2 ;
BLOCKING_STATUS
——————————————————————————–
MECK@machine1 ( SID=244 )  is blocking TAMY@machine2 ( SID=252 )
 
How to Identify the locked object
SQL> select * from v$lock ;
ADDR             KADDR                          SID TY        ID1        ID2             LMODE   REQUEST   CTIME     BLOCK
—————- —————-                    ———- –       ———- ———- ——-    ———-       ———- ———-
0000000451723DE8 0000000451723E20        244 TX    1310745    3139497          6          0         166           1
000000046032AFE0 000000046032B000        252 TX    1310745    3139497          0          6          33             0
 
TYPES OF LOCKS -  UL, TX amd TM
1. UL is a user-defined lock This is a lock defined with the DBMS_LOCK package.
2. TX lock is a row transaction lock; it’s acquired once for every transaction that changes data.Number of objects are being changed does not matter. The ID1 and ID2 columns point to the rollback segment and transaction table entries for that transaction.
3. TM lock is a DML lock. It’s acquired once for each object that’s being changed. The ID1 column identifies the object being modified.
So to find the object that is being blocked we can use ID1 from the v$lock.
SQL> select object_name from dba_objects where object_id=307193;
OBJECT_NAME
————–
OBJ1
How to Identify the locked row ?
SQL> select do.object_name,
row_wait_obj#, do.data_object_id, row_wait_file#, row_wait_block#, row_wait_row#,
dbms_rowid.rowid_create ( 1, do.data_object_id, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW# )
from v$session s, dba_objects do
where sid=252
and s.ROW_WAIT_OBJ# = do.OBJECT_ID ;
OBJECT_NAME
——————————————————————————–
ROW_WAIT_OBJ# DATA_OBJECT_ID ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
————- ————– ————– ————— ————-
DBMS_ROWID.ROWID_C
——————
OBJ1
307193         307193              5             455             0
AABK/5AAFAAAAHHAAA

From this, we get the row directly:
SQL> select * from obj1 where rowid=’ AABK/5AAFAAAAHHAAA’ ;
Getting the sql query that is being blocked
If you got the sid it should be easy by using the following sql :
SQL>select s.sid, q.sql_text from v$sqltext q, v$session s
where q.address = s.sql_address
and s.sid = 252;
SID SQL_TEXT
—– —————————————————————-
252 update obj1 set bar=:”SYS_B_0″ where bar=:”SYS_B_1″
Finding the blocking session SID and Serial#.
SQL> Select blocking_session, sid, serial#, wait_class,seconds_in_wait From v$session where blocking_session is not NULL order by blocking_session;
BLOCKING_SESSION     SID    SERIAL#  WAIT_CLASS     SECONDS_IN_WAIT
—————- ———- ———- ————————————————–
244                             252  11049       Application        1634
Solution to resolve locking
Kill the blocking session.
SQL> alter system kill session 244,11049′ immediate;
System altered.
 

Monday, June 29, 2015

sp_whoisactive and sp_who3

For looking into some SQL performance problems on systems I normally use these procedures.
sp_whoisactive 
sp_who3 

On running sp_whoisactive, if the output is showing a CXPACKET wait type that’s when sp_who3 comes into play.  Running sp_who3 with a SPID number after the procedure like “exec sp_who3 125″ will give you the wait type for each thread within the process.
When doing this recently on a system sp_whoisactive showed me that CXPACKET was the wait type.  After digging into the process with sp_who3 I saw that one of the threads was waiting on SOS_SCHEDULER_YIELD.  I then used sp_whoisactive to get the execution plan showing me the missing index which needed to be created.  In this case there was a clustered index on the table which was being scanned.  Based on the page count output from SET STATISTICS IO we were scanning the entire table every time the query was run.  This massively expensive query was causing the query to parallelize and the run time to go insanely high.
Hopefully you’ll find these stored procedures to be useful in your performance troubleshooting.  They aren’t hard to use, but they sure are useful.

Monday, June 22, 2015

sp_who3 - A new version of sp_who2

While working I came across this interesting version of sp_who2 named as sp_who3

It can be most useful when trying to diagnose slow running queries as it can provide a wealth of information in a single screen.
CREATE PROCEDURE sp_who3 


    @SessionID int = NULL

AS
BEGIN
SELECT
    SPID                = er.session_id 
    ,Status             = ses.status 
    ,[Login]            = ses.login_name 
    ,Host               = ses.host_name 
    ,BlkBy              = er.blocking_session_id 
    ,DBName             = DB_Name(er.database_id) 
    ,CommandType        = er.command 
    ,SQLStatement       = 
        SUBSTRING
        ( 
            qt.text, 
            er.statement_start_offset/2, 
            (CASE WHEN er.statement_end_offset = -1 
                THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2 
                ELSE er.statement_end_offset 
                END - er.statement_start_offset)/2 
        ) 
    ,ObjectName         = OBJECT_SCHEMA_NAME(qt.objectid,dbid) + '.' + OBJECT_NAME(qt.objectid, qt.dbid) 
    ,ElapsedMS          = er.total_elapsed_time 
    ,CPUTime            = er.cpu_time 
    ,IOReads            = er.logical_reads + er.reads 
    ,IOWrites           = er.writes 
    ,LastWaitType       = er.last_wait_type 
    ,StartTime          = er.start_time 
    ,Protocol           = con.net_transport 
    ,ConnectionWrites   = con.num_writes 
    ,ConnectionReads    = con.num_reads 
    ,ClientAddress      = con.client_net_address 
    ,Authentication     = con.auth_scheme 
FROM sys.dm_exec_requests er 
LEFT JOIN sys.dm_exec_sessions ses ON ses.session_id = er.session_id 
LEFT JOIN sys.dm_exec_connections con  ON con.session_id = ses.session_id 
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) as qt 
WHERE er.session_id > 50 
    AND @SessionID IS NULL OR er.session_id = @SessionID 
ORDER BY
    er.blocking_session_id DESC
    ,er.session_id 
  
END

Usage:
exec sp_who3

Friday, August 16, 2013

SQL Optimization



1) The sql query becomes faster if you use the actual columns names in SELECT statement instead of than '*'. 
If we use '*' , then sql takes time to expand it. Though time taken is very less but in large and complex queries, it can be a considerable factor.
For Example: Write the query as
SELECT id, first_name, last_name, age, subject FROM student_details;
Instead of:
SELECT * FROM student_details;

2) HAVING clause is used to filter the rows after all the rows are selected. It is just like a filter. Do not use HAVING clause for any other purposes.
For Example: Write the query as
SELECT subject, count(subject) FROM student_details WHERE subject != 'Science' AND subject != 'Maths' GROUP BY subject;
Instead of:
SELECT subject, count(subject) FROM student_details GROUP BY subject HAVING subject!= 'Vancouver' AND subject!= 'Toronto';

3) Sometimes you may have more than one subqueries in your main query. Try to minimize the number of subquery block in your query.
For Example: Write the query as
SELECT name FROM employee WHERE (salary, age ) = (SELECT MAX (salary), MAX (age) FROM employee_details) AND dept = 'Electronics';
Instead of:
SELECT name FROM employeeWHERE salary = (SELECT MAX(salary) FROM employee_details) AND age = (SELECT MAX(age) FROM employee_details) AND emp_dept = 'Electronics';

4) Use operator EXISTS, IN and table joins appropriately in your query.
a) Usually IN has the slowest performance.
b) IN is efficient when most of the filter criteria is in the sub-query.
c) EXISTS is efficient when most of the filter criteria is in the main query.
For Example: Write the query as
Select * from product p where EXISTS (select * from order_items o where o.product_id = p.product_id)
Instead of:
Select * from product p where product_id IN (select product_id from order_items

5) Use EXISTS instead of DISTINCT when using joins which involves tables having one-to-many relationship.
For Example: Write the query as
SELECT d.dept_id, d.dept FROM dept d WHERE EXISTS ( SELECT 'X' FROM employee e WHERE e.dept = d.dept);
Instead of:
SELECT DISTINCT d.dept_id, d.dept FROM dept d,employee e WHERE e.dept = e.dept;

6) Try to use UNION ALL in place of UNION.
For Example: Write the query as
SELECT id, first_name FROM student_details_class10 SELECT id, first_name FROM sports_team;
Instead of:
SELECT id, first_name, subject FROM student_details_class10 UNION SELECT id, first_name FROM sports_team;

7) Be careful while using conditions in WHERE clause.
For Example: Write the query as
SELECT id, first_name, age FROM student_details WHERE age > 10;
Instead of:
SELECT id, first_name, age FROM student_details WHERE age != 10;
Write the query as
SELECT id, first_name, age FROM student_details WHERE first_name LIKE 'Chan%';
Instead of:
SELECT id, first_name, age FROM student_details WHERE SUBSTR(first_name,1,3) = 'Cha';
Write the query as
SELECT product_id, product_name FROM product WHERE unit_price BETWEEN MAX(unit_price) and MIN(unit_price)
Instead of:
SELECT product_id, product_name FROM product WHERE unit_price >= MAX(unit_price) and unit_price <= MIN(unit_price)
Write the query as
SELECT id, first_name, age FROM student_details WHERE age > 10;
Instead of:
SELECT id, first_name, age FROM student_details WHERE age NOT = 10;
8)  To store large binary objects, first place them in the file system and add the file path in the database.
9) To write queries which provide efficient performance follow the general SQL standard rules.
a) Use single case for all SQL verbs
b) Begin all SQL verbs on a new line
c) Separate all words with a single space
d) Right or left aligning verbs within the initial SQL verb