How to capture computer screen using Java?

screen capture macbook and desktop

Abstract Window Toolkit (AWT)
           AWT used to create and manage windows. It is used to create windows that run in a GUI environment. Swing is built on base of AWT. Swing is using AWT directly or indirectly to provide you richer user interface. AWT is placed under java.awt package.

We will use Abstract Window Toolkit to create screen capture program. For the sake of convenience, I’m executing example from main method. Following example will capture whole screen of your system.
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * @author javaQuery
 */
public class ImageCapture {
    public static void main(String[] args) throws AWTException, IOException {
        /* File location is C:\Users\computerName\screenshot.png */
        File saveImage = new File(System.getProperty("user.home")+"\\screenshot.png");
        /* Define how much area you want to capture */
        Rectangle rectangle = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
        /* Capture image */
        BufferedImage imageCapture = new Robot().createScreenCapture(rectangle);
        /* Write BufferedImage to file */
        ImageIO.write(imageCapture, "png", saveImage);
    }
}

Variations

Rectangle(int width, int height);
Rectangle rectangle = new Rectangle(100,100);
It will capture an image of 100 x 100 (WxH) from top left corner of screen.

Rectangle(Dimension(int width, int height));
Rectangle rectangle = new Rectangle(new Dimension(100, 100));
It will capture an image of 100 x 100 (WxH) as specified its dimension. It’s same as above specification. To use dimension you need to import java.awt.Dimension class in your code.

Rectangle(Point(int x, int y));
Rectangle rectangle = new Rectangle(new Point(20, 20));
/* setSize(int width, int height) */
rectangle.setSize(100, 100);
Point is used to specify PointX and PointY of screen. It capture image block of given size from PointX and PointY. In this case it will capture an image of 100 x 100 (WxH) from point x = 20 and point y = 20. To use Point you need to import java.awt.Point class in your code.

Rectangle(Point(int x, int y), Dimension(int width, int height))
Rectangle rectangle = new Rectangle(new Point(10,10), new Dimension(100, 100));
Using Point and Dimension at the same time. Capture 100 x 100 (WxH) image from point x = 10 and point y = 10. You need to import both class as follow java.awt.Point and java.awt.Dimension.

Rectangle(int x, int y, int width, int height)
Rectangle rectangle = new Rectangle(20, 20, 100, 100);
It’s same as specifing PointX and PointY of screen and its width - height. It will capture an image of 100 x 100 (WxH) from point x = 20 and point y = 20.

You can use this program for different purposes. One of them is Key Logger in Java.

Database ORDER BY on two columns

ORDER BY two column_Microsoft_SQL_Server_MySQL

ORDER BY 
ORDER BY is used in database to sort data in Ascending or Descending order. ORDER BY keyword is available in all across different database platforms. It comes with two option ASC and DESC. If you don't apply order pattern(ASC or DESC) then it'll take ASC as default pattern.

Microsoft SQL Server and MySQL (Ascending) : SELECT * FROM user_master ORDER BY user_name
Microsoft SQL Server and MySQL (Descending) : SELECT * FROM user_master ORDER BY user_name DESC

I tested ORDER BY on two columns in Microsoft SQL Server and MySQL. You can share for other database platform.

Microsoft SQL Server Start up scripts
/* MSSQL tables and Insert queries */
/****** Object:  Table [dbo].[post]    Script Date: 05/22/2014 17:25:18 ******/
CREATE TABLE [dbo].[post](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [post] [varchar](max) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT post ON;
INSERT [dbo].[post] ([id], [post]) VALUES (1, N'Post 1')
INSERT [dbo].[post] ([id], [post]) VALUES (2, N'Post 2')
SET IDENTITY_INSERT post OFF;

/****** Object:  Table [dbo].[comments]    Script Date: 05/22/2014 17:25:18 ******/
CREATE TABLE [dbo].[comments](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [comment] [varchar](max) NULL,
 [postID] [int] NOT NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT comments ON;
INSERT [dbo].[comments] ([id], [comment], [postID]) VALUES (1, N'comment 1 of 1', 1)
INSERT [dbo].[comments] ([id], [comment], [postID]) VALUES (2, N'comment 2 of 1', 1)
INSERT [dbo].[comments] ([id], [comment], [postID]) VALUES (3, N'comment 1 of 2', 2)
INSERT [dbo].[comments] ([id], [comment], [postID]) VALUES (4, N'comment 2 of 2', 2)
INSERT [dbo].[comments] ([id], [comment], [postID]) VALUES (5, N'comment 3 of 2', 2)
SET IDENTITY_INSERT comments OFF;

MySQL Start up scripts
/* MySQL tables and Insert queries */
/****** Object:  Table post    Script Date: 05/22/2014 17:25:18 ******/
CREATE TABLE `post` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `post` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT post (id, post) VALUES (1, 'Post 1');
INSERT post (id, post) VALUES (2, 'Post 2');

/****** Object:  Table comments    Script Date: 05/22/2014 17:25:18 ******/
CREATE TABLE `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `comment` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `postID` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT comments (id, comment, postID) VALUES (1, 'comment 1 of 1', 1);
INSERT comments (id, comment, postID) VALUES (2, 'comment 2 of 1', 1);
INSERT comments (id, comment, postID) VALUES (3, 'comment 1 of 2', 2);
INSERT comments (id, comment, postID) VALUES (4, 'comment 2 of 2', 2);
INSERT comments (id, comment, postID) VALUES (5, 'comment 3 of 2', 2);

ORDER BY on Single Column
SELECT *
FROM post p
LEFT JOIN comments c
ON p.id = c.postID
ORDER BY p.id DESC;

ORDER BY on Two Columns
SELECT *
FROM post p
LEFT JOIN comments c
ON p.id = c.postID
ORDER BY p.id DESC, c.id DESC;

  • You can't apply ORDER BY on two columns within same table. If you apply ORDER BY on same table. It'll take last column name and apply ORDER BY pattern on it.

How to create Key logger in Java?

Are you agree on statement "We can't create key logger in Java". I know most of you say this statement is correct. Because we know that Java can't read anything outside of JVM (Java Virtual Machine). Even I was thinking same but my colleague was searching on the same. He found API called jNativeHook which makes it happen..

jNativeHook Features
  • Global Keyboard Listener
  • Global Mouse Listener
  • Global Mouse Wheel Listener

How it manage to capture key strokes from other application or anywhere in system?
Well jNativeHook using other programming language to capture key strokes and pass it to your application. Its using

  • .dll (Dynamic Link Library) for windows.
  • .dylib (Xcode Dynamic Library) for mac
  • .so (Shared object) for linux

jNativeHook in action
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
/**
 * @author javaQuery
 * Global Keyboard Listener
 */
public class jNativeHookExample implements NativeKeyListener {

    /* Key Pressed */
    public void nativeKeyPressed(NativeKeyEvent e) {
        System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

        /* Terminate program when one press ESCAPE */
        if (e.getKeyCode() == NativeKeyEvent.VK_ESCAPE) {
            GlobalScreen.unregisterNativeHook();
        }
    }

    /* Key Released */
    public void nativeKeyReleased(NativeKeyEvent e) {
        System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
    }

    /* I can't find any output from this call */
    public void nativeKeyTyped(NativeKeyEvent e) {
        System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
    }

    public static void main(String[] args) {
        try {
            /* Register jNativeHook */
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            /* Its error */
            System.err.println("There was a problem registering the native hook.");
            System.err.println(ex.getMessage());
            System.exit(1);
        }

        /* Construct the example object and initialze native hook. */
        GlobalScreen.getInstance().addNativeKeyListener(new jNativeHookExample());
    }
}

Known Issues
  • The library does not receive events after waking from a sleep state on Unix/Linux.
  • Users on Windows may experience a lapse in event data while using Remote Desktop in full screen mode.

Useful Links
Download API: https://code.google.com/p/jnativehook/downloads/list
Examples: https://code.google.com/p/jnativehook/wiki/examples

Check out jNativeHook project home page for more information and details

Custom Table Schema for Microsoft SQL Server

Now a days I'm working lot on database. I took switch for a while to learn basics of database. For my convenience I created Microsoft SQL Server Stored Procedure that helps us to find all constraints on table in one shot.

Microsoft SQL Management Studio also provide same data but display in multiple tables. I merged all that data in one single table so that data can be easily copied to Microsoft Excel or Google sheet. It also provide option to find column level constraints.

Execute below Stored Procedure in your Microsoft SQL Server... Or You can download same SQL script from here

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF(OBJECT_ID('usp_TableSchema') IS NOT NULL)
 DROP PROCEDURE usp_TableSchema;
GO
CREATE PROCEDURE usp_TableSchema
@TableName varchar(200),
@ColumnName varchar(200)
AS
BEGIN
 /**
  * @author javaQuery
  * @date 7th May, 2014
  * www.javaquery.com
  */
 /* Variable declaration */
 DECLARE @CURSOR_LOOP_ON_COLUMN CURSOR;
 DECLARE @GET_COLUMN_NAME VARCHAR(200);
 DECLARE @GET_COLUMN_DATA_TYPE VARCHAR(200);
 
 DECLARE @CURSOR_LOOP_ON_INDEX CURSOR;
 DECLARE @GET_INDEX_NAME VARCHAR(200);
 DECLARE @GET_INDEX_INCLUDED VARCHAR(200);
 DECLARE @COUNT INT = 1;

 DECLARE @CURSOR_LOOP_ON_FK CURSOR;
 DECLARE @GET_FK_TABLE_NAME VARCHAR(200);
 DECLARE @GET_FK_COLUMN_NAME VARCHAR(200);
 DECLARE @GET_FK_CONSTRAINT_NAME VARCHAR(200);

 DECLARE @GET_INDEX_COUNT INT;
 DECLARE @GET_FK_COUNT INT;
 DECLARE @CURRENT_FK_INDEX INT;

 /* Temporary table to hold final records */
 CREATE TABLE #TABLE_SCHEMA
 ( 
  COLUMN_NAME VARCHAR(200),
  COLUMN_TYPE VARCHAR(200),
  PK VARCHAR(5),
  PK_CONSTRAINT_NAME VARCHAR(200),
  UNIQUE_KEY VARCHAR(5),
  UNIQUE_KEY_NAME VARCHAR(200),
  DF_CONSTRAINT_NAME VARCHAR(200),
  DF_CONSTRAINT_VALUE VARCHAR(200),
  FK_CONSTRAINT_ON_COLUMN VARCHAR(200),
  FK_REFERENCE_TABLE VARCHAR(200),
  FK_REFERENCE_COLUMN VARCHAR(200),
  COLUMN_AS_FK_ON_TABLE VARCHAR(200),
  COLUMN_AS_FK_ON_TABLE_COLUMN VARCHAR(200),
  COLUMN_AS_FK_CONSTRAINT_NAME VARCHAR(200),
  IDX_NAME VARCHAR(200),
  IDX_COLUMN_INCLUDED VARCHAR(5),
  SEARCH_COLUMN VARCHAR(200)
 ); 

 /* Temporary table to hold 'PRIMARY KEY CONSTRAINTS' */
 CREATE TABLE #PK_CONSTRAINT
 (
  PK_COLUMN_NAME VARCHAR(200),
  PK_CONSTRAINT_NAME VARCHAR(200)
 );
 
 /* Fetch all Primary keys on table */
 INSERT INTO #PK_CONSTRAINT(PK_COLUMN_NAME,PK_CONSTRAINT_NAME)
 SELECT COLUMN_NAME, tc.CONSTRAINT_NAME 
 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
 INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
 ON tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
 AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
 AND kcu.TABLE_NAME = @TableName
 ORDER BY kcu.ORDINAL_POSITION

 /* Temporary table to hold 'UNIQUE KEY CONSTRAINTS' */
 CREATE TABLE #UNIQUE_KEY
 (
  UN_COLUMN_NAME VARCHAR(200),
  UN_CONSTRAINT_NAME VARCHAR(200)
 );
 
 /* Fetch all Unique keys on table */
 INSERT INTO #UNIQUE_KEY(UN_COLUMN_NAME, UN_CONSTRAINT_NAME)
 SELECT COLUMN_NAME, tc.CONSTRAINT_NAME 
 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
 INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
 ON tc.CONSTRAINT_TYPE = 'UNIQUE'
 AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
 AND kcu.TABLE_NAME = @TableName
 ORDER BY kcu.ORDINAL_POSITION

 /* Temporary table to hold 'DEFAULT CONSTRAINTS' */
 CREATE TABLE #DF_CONSTRAINT
 (
  DF_COLUMN_NAME VARCHAR(200),
  DF_CONSTRAINT_NAME VARCHAR(200),
  DF_CONSTRAINT_VALUE VARCHAR(200)
 );
 
 /* Fetch all default constraints on table */
 INSERT INTO #DF_CONSTRAINT (DF_COLUMN_NAME, DF_CONSTRAINT_NAME, DF_CONSTRAINT_VALUE)
 SELECT col.name, df.name, definition 
 FROM sys.columns col
 LEFT JOIN sys.default_constraints df
 ON col.default_object_id = df.object_id
 WHERE OBJECT_NAME(col.object_id) = @TableName
 AND OBJECT_NAME(df.parent_object_id) = @TableName;
 
 /* Temporary table to hold 'FOREIGN KEY CONSTRAINTS' */
 CREATE TABLE #FK_CONSTRAINT_CURRENT_COLUMN
 (
  COLUMN_NAME VARCHAR(200),
  FK_CUURENT_TABLE_NAME VARCHAR(200),
  FK_CURRENT_COLUMN_NAME VARCHAR(200),
  FK_CURRENT_CONSTRAINT_NAME VARCHAR(200)
 );
 
 /* Find all referencing Foreign key constraints on table */
 INSERT INTO #FK_CONSTRAINT_CURRENT_COLUMN (COLUMN_NAME, FK_CUURENT_TABLE_NAME,FK_CURRENT_COLUMN_NAME, FK_CURRENT_CONSTRAINT_NAME)
 SELECT col1.name, tab2.name, col2.name, obj.name
 FROM sys.foreign_key_columns fkc
 INNER JOIN sys.objects obj
  ON obj.object_id = fkc.constraint_object_id
 INNER JOIN sys.tables tab1
  ON tab1.object_id = fkc.parent_object_id
 INNER JOIN sys.columns col1
  ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
 INNER JOIN sys.tables tab2
  ON tab2.object_id = fkc.referenced_object_id
 INNER JOIN sys.columns col2
  ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
 WHERE tab1.name = @TableName
 
 /* Temporary table to hold 'FOREIGN KEY CONSTRAINTS' */
 CREATE TABLE #FK_CONSTRAINT
 (
  ID numeric(19, 0) IDENTITY(1,1) NOT NULL,
  COLUMN_NAME VARCHAR(200),
  FK_TABLE_NAME VARCHAR(200),
  FK_COLUMN_NAME VARCHAR(200),
  FK_CONSTRAINT_NAME VARCHAR(200)
 );
 
 /* Find all referencing Foreign key constraints on table */
 INSERT INTO #FK_CONSTRAINT (COLUMN_NAME, FK_TABLE_NAME,FK_COLUMN_NAME, FK_CONSTRAINT_NAME)
 SELECT col2.name, tab1.name, col1.name, obj.name
 FROM sys.foreign_key_columns fkc
 INNER JOIN sys.objects obj
  ON obj.object_id = fkc.constraint_object_id
 INNER JOIN sys.tables tab1
  ON tab1.object_id = fkc.parent_object_id
 INNER JOIN sys.columns col1
  ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
 INNER JOIN sys.tables tab2
  ON tab2.object_id = fkc.referenced_object_id
 INNER JOIN sys.columns col2
  ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
 WHERE tab2.name = @TableName
 
 /* Temporary table to hold 'INDICES' */
 CREATE TABLE #COLUMN_INDICES
 (
  ID numeric(19, 0) IDENTITY(1,1) NOT NULL,
  INDEX_COLUMN_NAME VARCHAR(200),
  INDEX_NAME VARCHAR(200),
  INDEX_COLUMN_INCLUDED VARCHAR(5)
 );
 
 /* Loop through each column name */
 SET @CURSOR_LOOP_ON_COLUMN = CURSOR FOR SELECT COLUMN_NAME, DATA_TYPE
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE TABLE_NAME = @TableName
           ORDER BY ORDINAL_POSITION;
 OPEN @CURSOR_LOOP_ON_COLUMN
  FETCH NEXT
   FROM @CURSOR_LOOP_ON_COLUMN INTO @GET_COLUMN_NAME, @GET_COLUMN_DATA_TYPE
   WHILE @@FETCH_STATUS = 0
   BEGIN 
    /* Fetch all indices on column */
    INSERT INTO #COLUMN_INDICES (INDEX_COLUMN_NAME, INDEX_NAME, INDEX_COLUMN_INCLUDED)
    SELECT DISTINCT c.name, ind.name, CASE WHEN ic.is_included_column = 0 THEN 'NO' WHEN ic.is_included_column != 0 THEN 'YES' END
    FROM sys.indexes ind
    RIGHT JOIN sys.tables t
    ON ind.object_id = t.object_id
    RIGHT JOIN sys.columns c
    ON t.object_id = c.object_id
    RIGHT JOIN sys.index_columns ic
    ON ind.index_id = ic.index_id
    AND c.column_id = ic.column_id
    WHERE ind.is_primary_key = 0
    AND ind.is_unique_constraint = 0
    AND t.is_ms_shipped = 0
    AND ind.name is not null
    AND ind.is_unique in (0,1)
    AND t.name = @TableName
    AND c.name = @GET_COLUMN_NAME
    AND OBJECT_NAME(ic.object_id) = @TableName;
    
    /* Fill up record table */
    INSERT INTO #TABLE_SCHEMA
      (COLUMN_NAME, COLUMN_TYPE, PK, PK_CONSTRAINT_NAME, UNIQUE_KEY, UNIQUE_KEY_NAME
      ,DF_CONSTRAINT_NAME, DF_CONSTRAINT_VALUE, FK_CONSTRAINT_ON_COLUMN, FK_REFERENCE_TABLE, FK_REFERENCE_COLUMN,
      COLUMN_AS_FK_ON_TABLE, COLUMN_AS_FK_ON_TABLE_COLUMN, COLUMN_AS_FK_CONSTRAINT_NAME, IDX_NAME, IDX_COLUMN_INCLUDED,
      SEARCH_COLUMN)
    SELECT @GET_COLUMN_NAME,
        @GET_COLUMN_DATA_TYPE,
        CASE WHEN (SELECT COUNT(*) FROM #PK_CONSTRAINT WHERE PK_COLUMN_NAME = @GET_COLUMN_NAME) > 0 THEN 'YES' END,
        (SELECT PK_CONSTRAINT_NAME FROM #PK_CONSTRAINT WHERE PK_COLUMN_NAME = @GET_COLUMN_NAME),
        CASE WHEN (SELECT COUNT(*) FROM #UNIQUE_KEY WHERE UN_COLUMN_NAME = @GET_COLUMN_NAME) > 0 THEN 'YES' END,
        (SELECT UN_CONSTRAINT_NAME FROM #UNIQUE_KEY WHERE UN_COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT DF_CONSTRAINT_NAME FROM #DF_CONSTRAINT WHERE DF_COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT DF_CONSTRAINT_VALUE FROM #DF_CONSTRAINT WHERE DF_COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT FK_CURRENT_CONSTRAINT_NAME FROM #FK_CONSTRAINT_CURRENT_COLUMN WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT FK_CUURENT_TABLE_NAME FROM #FK_CONSTRAINT_CURRENT_COLUMN WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT FK_CURRENT_COLUMN_NAME FROM #FK_CONSTRAINT_CURRENT_COLUMN WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT TOP 1 FK_TABLE_NAME FROM #FK_CONSTRAINT WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT TOP 1 FK_COLUMN_NAME FROM #FK_CONSTRAINT WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT TOP 1 FK_CONSTRAINT_NAME FROM #FK_CONSTRAINT WHERE COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT TOP 1 INDEX_NAME FROM #COLUMN_INDICES WHERE INDEX_COLUMN_NAME = @GET_COLUMN_NAME),
        (SELECT TOP 1 INDEX_COLUMN_INCLUDED FROM #COLUMN_INDICES WHERE INDEX_COLUMN_NAME = @GET_COLUMN_NAME),
        @GET_COLUMN_NAME;
    
    SELECT @GET_FK_COUNT = COUNT(*) FROM #FK_CONSTRAINT WHERE COLUMN_NAME = @GET_COLUMN_NAME;
    SELECT TOP 1 @CURRENT_FK_INDEX = ID FROM #FK_CONSTRAINT WHERE COLUMN_NAME = @GET_COLUMN_NAME;
    SELECT @GET_INDEX_COUNT = COUNT(*) FROM #COLUMN_INDICES WHERE INDEX_COLUMN_NAME = @GET_COLUMN_NAME;
    
    /* Below logic is to fiil up Foreign key and index in one row */    
    SET @COUNT = 1;
        
    WHILE (@COUNT < @GET_INDEX_COUNT)
    BEGIN
     SET @GET_FK_TABLE_NAME = NULL;
     SET @GET_FK_COLUMN_NAME = NULL;
     SET @GET_FK_CONSTRAINT_NAME = NULL;
    
     SELECT TOP 1 @CURRENT_FK_INDEX = ID, @GET_FK_TABLE_NAME = FK_TABLE_NAME, 
         @GET_FK_COLUMN_NAME = FK_COLUMN_NAME, @GET_FK_CONSTRAINT_NAME = FK_CONSTRAINT_NAME
     FROM #FK_CONSTRAINT 
     WHERE ID > @CURRENT_FK_INDEX AND COLUMN_NAME = @GET_COLUMN_NAME;
        
     INSERT INTO #TABLE_SCHEMA 
       (COLUMN_NAME, COLUMN_TYPE, COLUMN_AS_FK_ON_TABLE, COLUMN_AS_FK_ON_TABLE_COLUMN, COLUMN_AS_FK_CONSTRAINT_NAME
       ,IDX_NAME, IDX_COLUMN_INCLUDED, SEARCH_COLUMN)
     SELECT TOP 1 '', '', @GET_FK_TABLE_NAME, @GET_FK_COLUMN_NAME, @GET_FK_CONSTRAINT_NAME
        ,INDEX_NAME, INDEX_COLUMN_INCLUDED, @GET_COLUMN_NAME
     FROM #COLUMN_INDICES 
     WHERE ID > @COUNT 
     AND INDEX_COLUMN_NAME = @GET_COLUMN_NAME;
     
     SET @COUNT = @COUNT + 1;
    END   
        
    IF(@GET_FK_COUNT > @GET_INDEX_COUNT)
    BEGIN
     SET @COUNT = 1;
     WHILE(@COUNT < @CURRENT_FK_INDEX)
     BEGIN
      SET @COUNT = @CURRENT_FK_INDEX;
           
      INSERT INTO #TABLE_SCHEMA 
        (COLUMN_NAME, COLUMN_TYPE, COLUMN_AS_FK_ON_TABLE, COLUMN_AS_FK_ON_TABLE_COLUMN, COLUMN_AS_FK_CONSTRAINT_NAME, SEARCH_COLUMN)
      SELECT TOP 1 '', '', FK_TABLE_NAME, FK_COLUMN_NAME, FK_CONSTRAINT_NAME, @GET_COLUMN_NAME
      FROM #FK_CONSTRAINT 
      WHERE ID > @CURRENT_FK_INDEX 
      AND COLUMN_NAME = @GET_COLUMN_NAME;
      
      SELECT TOP 1 @CURRENT_FK_INDEX = ID 
      FROM #FK_CONSTRAINT 
      WHERE ID > @CURRENT_FK_INDEX AND COLUMN_NAME = @GET_COLUMN_NAME;
     END
     
    END
    
    /* Flush all records from #COLUMN_INDICES table */
    TRUNCATE TABLE #COLUMN_INDICES;
      
    FETCH NEXT
    FROM @CURSOR_LOOP_ON_COLUMN INTO @GET_COLUMN_NAME, @GET_COLUMN_DATA_TYPE
   END
 CLOSE @CURSOR_LOOP_ON_COLUMN
 DEALLOCATE @CURSOR_LOOP_ON_COLUMN
 
 IF(@ColumnName IS NOT NULL AND @ColumnName != '')
 BEGIN
    SELECT COLUMN_NAME, COLUMN_TYPE, PK, PK_CONSTRAINT_NAME, UNIQUE_KEY, UNIQUE_KEY_NAME
       ,DF_CONSTRAINT_NAME, DF_CONSTRAINT_VALUE, FK_CONSTRAINT_ON_COLUMN, FK_REFERENCE_TABLE, FK_REFERENCE_COLUMN,
       COLUMN_AS_FK_ON_TABLE, COLUMN_AS_FK_ON_TABLE_COLUMN, COLUMN_AS_FK_CONSTRAINT_NAME, IDX_NAME, IDX_COLUMN_INCLUDED
    FROM #TABLE_SCHEMA 
   WHERE SEARCH_COLUMN = @ColumnName; 
 END
 ELSE
 BEGIN
    SELECT COLUMN_NAME, COLUMN_TYPE, PK, PK_CONSTRAINT_NAME, UNIQUE_KEY, UNIQUE_KEY_NAME
       ,DF_CONSTRAINT_NAME, DF_CONSTRAINT_VALUE, FK_CONSTRAINT_ON_COLUMN, FK_REFERENCE_TABLE, FK_REFERENCE_COLUMN,
       COLUMN_AS_FK_ON_TABLE, COLUMN_AS_FK_ON_TABLE_COLUMN, COLUMN_AS_FK_CONSTRAINT_NAME, IDX_NAME, IDX_COLUMN_INCLUDED 
    FROM #TABLE_SCHEMA; 
 END
END

Execute usp_TableSchema
usp_TableSchema accepts two arguments @TableName, @ColumnName

  • To get table level constraints fire this command exec usp_TableSchema 'table_name', ''
  • To get constraints on particular column fire this command exec usp_TableSchema 'table_name', 'column_name'

Click to enlarge

Microsoft SQL Studio Management Shortcut
Select TableName and press Alt + F1

How to connect Microsoft SQL Server from Java?

Now a days all major applications in Java using Hibernate to support multiple dialect. However Today I'm going to post an article "Connecting Microsoft SQL Server using Java code" by using SQL Server library.

Change credential in below code and test your connection to Microsoft SQL Server
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @author javaQuery
 * This program demonstrate connection between Java and Microsoft SQL Server.
 */
public class MSSQLConnect {

    public static void main(String[] args) {
        /**
         * Driver to connect database.
         * Database credentials.
         */
        String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        String url = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=javaQuery";
        String username = "sa";
        String password = "airborne";
        try {
            /* Load database driver */
            Class.forName(driver);
            /* Establish database connection */
            Connection con = DriverManager.getConnection(url, username, password);
            /* Run query */
            PreparedStatement stmt = con.prepareStatement("select * from user_master");
            /* Get return result */
            ResultSet resultset = stmt.executeQuery();
            /* Loop through every row  */
            while (resultset.next()) {
                System.out.println(resultset.getString("Firstname")+" "+resultset.getString("Lastname"));
            }
            /* Close result set */
            resultset.close();
            /* Close database connection */
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Download Microsoft SQL Server API from here http://goo.gl/HT6HA6

Error Code: 1267. Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '='

To solve this error I pulled my hair and scrolled through so many blog articles and forum. Finally today I came up with different solutions either can help you.

Note in Public Interest: MySQL has strange behavior, I don't know which kinda developer working on it? So if you are facing an issue right now may not occur after day or so.

Scenario: Most of our clients using Microsoft SQL Server but two or three client want MySQL Server on their server so we've to work on it. We deployed our code on MySQL Server. Our product has so many Stored Procedures, It was working fine but two days back they were facing same error.

Solution 1: Check your query related column's collation using following query and change as per your requirement.
/* Show all columns and its collation */
SELECT * 
FROM information_schema.columns 
WHERE table_schema = DATABASE();
/* ALTER TABLE  MODIFY  VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci; to change column collation */
ALTER TABLE address MODIFY address1 VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Solution 2: Check your table's collation using following query and change as per your requirement.
/* Show all tables and its collation */
SHOW TABLE STATUS;
/* ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE <collation>; to change table collation. */
ALTER TABLE actor CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Solution 3: Check collation of your database and change as per your requirement.
/* To check your database collation */
SELECT * 
FROM information_schema.SCHEMATA S
WHERE schema_name = DATABASE(); 
/* ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE <collation>; To change database collation */
ALTER DATABASE test CHARACTER SET utf8 COLLATE utf8_unicode_ci;

I did above suggested all changes still I was facing same error. I dig down further and found that my connection's collation is utf8_general_ci and database collation is utf8_unicode_ci. To understand the my ground follow below image.

utf8_unicode_ci - utf8_general_ci


Solution 4: Use COLLATE within inline query as follow.
SELECT *
FROM actor 
WHERE name = tmp_VARIABLE
COLLATE utf8_unicode_ci; 

Solution 5: Change parameter's character set in case of Stored Procedure or functions.
CREATE PROCEDURE proc_test (param1 VARCHAR (10) charset utf8, param2 int)

Solution 6: MySQL configuration changes
Place following lines under [mysqld] tag in MySQL configuration file lying under /etc/mysq/my.cnf [Linux] and C:\ProgramData\MySQL\MySQL Server 5.6\my.ini [Windows].
character-set-server=utf8
collation-server=utf8_unicode_ci

After change it'll look like as follow...
[mysqld]
character-set-server=utf8
collation-server=utf8_unicode_ci
Now restart MySQL Server.

In my case solution 4 and 5 worked like charm. I tried to change collation_connection variable using mysql configuration file but didn't get success to solve this issue. Please share your solution if you have any.

Special Thanks to:
- http://forums.mysql.com/read.php?103,265345,265579#msg-265579
- http://www.excindex.com/mysql/589131.html

MSSQL: Queries that do not return large result sets. Nonclustered Index limitation

What is Nonclustered Index?
A nonclustered index contains the index key values and row locators that point to the storage location of the table data.

Queries that do not return large result sets. - Nonclustered Index Design Guidelines
Source: http://technet.microsoft.com/en-us/library/ms179325(v=sql.105).aspx

We are using hibernate in our project to support multiple dialect. Its our routine process to get queries that are generated by hibernate. We do analysis on that queries and suggest indexes and other stuffs. We replaced ? in query with 0. We fired that query in Microsoft SQL Server Management Studio and Execution plan suggested index. We created index with bit modification. After executing same query again what we see is index is not used by query.

We were clueless why is database not using index. We went through lots of article but no one wrote specifically for this rule of nonclustered index. We did few more run on different tables and queries. We were not able to derive perfect rule that...

Database will not use Nonclustered Index when Its returning 'n' records.
It's yet to be discovered from my side. If you guys have perfect rule for this do share in comment. I'll put here if its really a case.

Case Scenario:
SELECT * 
FROM s_master this_ 
LEFT OUTER JOIN t_master tlist2_ 
ON this_.id = tlist2_.s_id 
WHERE this_.document_id = 0 
AND this_.library_id = 0
This query returned 2248 records and as Microsoft SQL server design guide line suggests, query won't use index. We replaced 0 with specific value and It started using Index.

Conclusion:
Nonclustered Index is only useful when you are sure that your query won't return much records.

You'd like to read more about index, scroll through this articles...

MSSQL: How to find all database indexes on column?

I was playing with MSSQL system tables for fun and popup one thing that lets try to find all indexes on column. I ended up with one long query so thought let me post it and you guys don't have work for this query again.

Professionals I don't have to explain much about these tables. Beginner try to work around this table. It'll help you lot in future, way to become database expert in other word Database Administrator(DBA).

/* Change table name and column name in where condition */
SELECT distinct ind.name AS [idx_name], t.name AS [table_name], c.name AS [column_name], ic.is_included_column
FROM sys.indexes ind 
RIGHT JOIN sys.tables t 
 ON ind.object_id = t.object_id 
RIGHT JOIN sys.columns c 
 ON t.object_id = c.object_id
RIGHT JOIN sys.index_columns ic 
 ON ind.index_id = ic.index_id
       AND c.column_id = ic.column_id
WHERE ind.is_primary_key = 0  
  AND ind.is_unique_constraint = 0 
  AND t.is_ms_shipped = 0
  AND ind.name IS NOT NULL
  AND ind.is_unique IN (0,1)
  AND t.name = 'table_name'
  AND c.name = 'column_name'
  AND OBJECT_NAME(ic.object_id) = 'table_name'
There ain't much to write for this query. Change table_name and column_name

Execution Plan in MSSQL Server

What is Execution Plan?
As word suggest, Its the plan that shows how actually database executes the query by analyzing available table information. It includes database indexes and statistics on that table.

Execution Plan is tool provided by MSSQL to optimize your queries. Its very popular in community of Database Administrator. Yet so many programmer not really aware of this tool. It helps me to analyze query on daily basis.

Advantages
Execution Plan show us what is cost of executing particular query. Its holds one unique feature that It suggest Index on table and also promising analysis of index compare to MSSQL Profiler. Execution plan we'll show you following statistics on any node.

  • Physical Operation
  • Logical Operation
  • Actual Number of Rows
  • Estimated I/O Cost
  • Estimated CPU Cost
  • Estimated Number of Executions
  • Number of Executions
  • Estimated Operator Cost
  • Estimated Subtree Cost
  • Estimated Number of Rows
  • Estimated Row Size
  • Actual Rebinds
  • Actual Rewinds
  • Ordered
  • NodeID
  • Seek Predicates

How to enable "Execution Plan" in MSSQL Server?
Find Execution Plan icon  in the top toolbar. Click on it to enable and disable or shortcut key Ctrl + m. You've to do it for each query windows.

Execution Plan in the Action
On my database I'm executing following query and lets see what Execution plan show us.
SELECT * 
FROM stage_master sm 
LEFT OUTER JOIN task_master tm 
ON sm.id = tm.stage_id 
WHERE sm.document_id = 4592
AND sm.library_id = 25614
And the Execution Plan

Click to enlarge
Whats it says?
Well I'm going to very brief on this as there are other things here not available in this execution plan like Parallelism other things that differ from query to query.

  • At the top green line says you should have index on table. It'll also generate query to create index. Right click on execution plan area then Missing Index Details. 
  • Thick line shows it is processing lots of information and has much cost on query. 
  • Hover your mouse pointer on any node it'll show you actual statistics as follow...

MySQL: Queries to 'Show All Database Indexes' and 'Drop All Table Indexes'

Database Index
A database index is a data structure that improves the speed of data retrieval operations on a database table at the cost of additional writes and the use of more storage space to maintain the extra copy of data. Indexes are used to quickly locate data without having to search every row in a database table every time a database table is accessed. Indexes can be created using one or more columns of a database table, providing the basis for both rapid random lookups and efficient access of ordered records.

As described above database index helps only for search operation. Insert, Update and Delete will suffer. Index should be created only selected fields based on your retrieval of data (Columns).

- Source (WikiPedia: http://en.wikipedia.org/wiki/Database_index)

In my previous article we discussed about MSSQL Indexes . Now we'll see how you can achieve same in MySQL. 

SHOW ALL INDEXES 
/* It'll show all indexes except Primary Key */
SELECT *
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = (SELECT DATABASE())
AND INDEX_NAME != 'PRIMARY';

DROP ALL TABLE INDEXES
Basic Syntax of dropping index is DROP INDEX INDEX_NAME ON TABLE_NAME; but to drop index in one single shot is not possible. You've to loop through all indexes of database. Thus, We've to use Stored Procedure in MySQL.
DROP PROCEDURE IF EXISTS usp_DropIndexOfTable;
DELIMITER $$
CREATE PROCEDURE usp_DropIndexOfTable(IN TableName VARCHAR(100))
BEGIN
 /**
  * @Created By: Vicky Thakor
  * @Created On: 6th March, 2014
  * This will delete all Indexes of table except Primary Key
  * 
  * @Test: CALL usp_DropIndexOfTable('user_master');
  */
 DECLARE v_finished INTEGER DEFAULT 0;
 DECLARE v_index varchar(200) DEFAULT "";
        DEClARE index_cursor CURSOR FOR 
        /* In below query remove TABLE_NAME criteria to remove all indexes */
        SELECT INDEX_NAME
  FROM INFORMATION_SCHEMA.STATISTICS
  WHERE TABLE_SCHEMA = (SELECT DATABASE())
  AND TABLE_NAME = TableName
  AND INDEX_NAME != 'PRIMARY';
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;

 DECLARE exit handler FOR sqlexception
 BEGIN
 -- ERROR
 SHOW ERRORS LIMIT 1;
 ROLLBACK;
 END;

 DECLARE exit handler FOR sqlwarning
 BEGIN
 -- WARNING
 SHOW WARNINGS LIMIT 1;
 ROLLBACK;
 END;

 OPEN index_cursor; 
  get_index: LOOP
   FETCH index_cursor INTO v_index;

   IF v_finished = 1 THEN 
    LEAVE get_index;
   END IF;
  
   SET @v_query = CONCAT('DROP INDEX ',v_index,' ON ', TableName);
   PREPARE stmt FROM @v_query;
   EXECUTE stmt;
   DEALLOCATE PREPARE stmt;
  END LOOP get_index;
       CLOSE index_cursor;
END$$
DELIMITER ;
Just fire above Stored Procedure in your database and then execute this stored procedure using
CALL usp_DropIndexOfTable('user_master'). You can modify above stored procedure according to your requirement.