5

I want to push the data from database to application instead of application pull the data. I have installed ms sql server and apache tomcat server. I have my application in apache tomcat, here I made connection to database. Now I want database send the data whenever there is update in data. But all I know is fetch the data from database is not good idea, because application needs to monitor the database for updated data will lead to fire the query for every 5 sec, this is not efficient as well.

I google it I got some answers they are Query Notification here, Sql server Agent Job to schedule the task automatically. If you have any other suggestion please post it.

OzrenTkalcecKrznaric
  • 5,535
  • 4
  • 34
  • 57
niren
  • 2,693
  • 8
  • 34
  • 58

1 Answers1

5

There surely are several possibilities to do that:

  • Implement unsafe CLR trigger
  • Implement unsafe CLR procedure
  • Use xp_cmdshell
  • Call web service
  • Use Query Notification

You can read a little about them in this discussion: Serial numbers, created and modified in SQL Server.

Personally I would prefer Query Notification over other methods, because it already has support fopr various cases (e.g. sync/async communication) and you don't have to reinvent the wheel. And is in your case recommended by Microsoft.

Polling is another method you've mentioned. It's is a more like traditional method and there can be some performance penalties related, but you shouldn't worry about them if you are careful enough. For example, if you already have an authentication built in your application, you can create another column in your Users table that is set if there are any changes related to that user. And then, there can be just a thread in your app that will perform a query every second against this table (even dirty reads with NOLOCK shouldn't be a problem here) and maintain some in-memory structure (e.g. thread-safe dictionary) that says which client should get pushed. Another thread polls your dictionary and when it finds there something for the client, performs a db query that extracts data and sends it to the client. This looks like a lot of unnccessary work, but at the end you get two independent workers which somewhat helps to separate concerns; first one is just an informer which performs 'lightweight' database polling; second one extract real data and performs server push. You can even optimize the push-worker in the way that when it runs, it checks if multiple clients need some data and then executes the select for all of those who need it. You would probably want the second worker to run less frequently than first one.

EDIT

If you wish to use non-.NET technology to achieve the same functionality, you will have to get more into SQL Server Service Broker. Query Notification is a simplified layer built in .NET on top of SQL Server Service Broker, and you would have to build at least part of that layer by yourself. This includes creating queue, message type, service and stored procedures with SEND and RECEIVE on the other side. You will have to take care of the conversation/dialog by yourself. SB is actually a async-messaging world adjusted to work in RDBMS environment, so you will see some new TSQL expressions. However, MSDN is here to help:

This could help as well: Externally activate non-.NET application from Service Broker

Example on how to code the stuff:

-- First you have to enable SB for your database
USE master
ALTER DATABASE Playground
SET ENABLE_BROKER
GO

USE Playground
GO

-- Then create a message type; usually it will be XML
-- because it's very easy to serialize/deserialize it
CREATE MESSAGE TYPE [//Playground/YourMessageType]
VALIDATION = WELL_FORMED_XML
GO

-- Then create a contract to have a rule for communication
-- Specifies who sends which message type
CREATE CONTRACT [//Playground/YourContract] (
    [//Playground/YourMessageType] SENT BY ANY)
GO

--Creates queues, one for initiator (1) and one for target (2)
CREATE QUEUE MyQueue1
GO
CREATE QUEUE MyQueue2
GO

-- Finally, configure services that 'consume' queues
CREATE SERVICE [//Playground/YourService1]
ON QUEUE MyQueue1 ([//Playground/YourContract])
GO

CREATE SERVICE [//Playground/YourService2] 
ON QUEUE MyQueue2 ([//Playground/YourContract])
GO

-- Now you can send a message from service to service using contract
DECLARE 
    @dHandle uniqueidentifier,
    @Msg nvarchar(max) 

BEGIN DIALOG @dHandle
    FROM SERVICE [//Playground/YourService1]
    TO SERVICE '//Playground/YourService2'
    ON CONTRACT [//Playground/YourContract]
WITH ENCRYPTION = OFF

SELECT @Msg = (
    SELECT TOP 3 *
    FROM Table1
    FOR XML PATH('row'), ROOT('Table1'))

;SEND ON CONVERSATION @dHandle 
MESSAGE TYPE [//Playground/YourMessageType] (@Msg)

PRINT @Msg
GO

-- To get the message on the other end, use RECEIVE
-- Execute this in another query window
DECLARE @dHandle uniqueidentifier
DECLARE @MsgType nvarchar(128)
DECLARE @Msg nvarchar(max)

;RECEIVE TOP(1)
    @dHandle = conversation_handle,
    @Msg = message_body,
    @MsgType = message_type_name
FROM MyQueue2

SELECT @MsgType 
SELECT @Msg

END CONVERSATION @dHandle 
GO
Community
  • 1
  • 1
OzrenTkalcecKrznaric
  • 5,535
  • 4
  • 34
  • 57
  • which method would be useful for my sql server edition, am using ms sql server 2012 express edition. My application in tomcat server is webMathemaica. – niren Jun 20 '13 at 08:05
  • Unfortunately I'm a spoiled brath using almost always standard/enterprise edition. I believe that in 2012 if you enable [Service Broker and other Query Notification stuff](http://msdn.microsoft.com/en-us/library/ms172133(v=vs.80).aspx), you shouldn't have any problems using [SqlDependency](http://msdn.microsoft.com/en-us/library/62xk7953.aspx) – OzrenTkalcecKrznaric Jun 20 '13 at 08:32
  • all the examples I see for the Query Notification they show in .Net applications only. can I implement this Query Notification for other client applications like jsp, etc? If I can where I can find good examples. – niren Jun 20 '13 at 09:34
  • after went through the document I come to know that I need to write a query in application side for notification request then the DB will register my request in subscription and If there is any change in the DB it will check subscription if the request is there it will send the message to the client. Now I don't how to write a query in application side to send notification request. – niren Jun 21 '13 at 08:03
  • There's an example in my answer. Use first part until SEND in e.g. trigger to send the message. Use last RECEIVE part in e.g. stored procedure from your application to get the message. – OzrenTkalcecKrznaric Jun 21 '13 at 14:24
  • Thank you @Ozren Tkalčec Krznarić I execute you answer it's working. I have another doubt and I asked another question go through this link [How does Sql server will identify Tomcat server?](http://stackoverflow.com/questions/17250574/how-does-tomcat-server-identified-by-sql-server) – niren Jun 23 '13 at 06:20
  • I tried it in same database it's working, so I accept the answer. but I want the concept work on database to application. How should I configure my application in tomcat server to make it work? – niren Jun 23 '13 at 08:35
  • There is no magic behind the SB tsql statements. If you can exec query from your application, you can exec RECEIVE as well. Common approach would be wrapping it into procedure and calling that procedure from app. Just set timeout to 0 (infinite) to avoid recalling every x secs. – OzrenTkalcecKrznaric Jun 23 '13 at 11:06
  • here I need to execute the application to get the message, but my requirement is user doesn't have access to application he can access database to modify. – niren Jun 23 '13 at 12:52
  • You don' t have this requirement in the question. Just to clarify, there is some user that will access database directly (e.g. from Management Studio) and update data in the table. If that happens, your code has to catch it and send message to your application. Right? – OzrenTkalcecKrznaric Jun 24 '13 at 05:25
  • Ok, then you need to send the message from the trigger. There are more sophisticated ways but this one should be straight and simple. I suggest you to open another question on implications of using SEND inside trigger. – OzrenTkalcecKrznaric Jun 24 '13 at 09:23