I work for an Insurance Company and creating a custom application. When we apply a coverage to a policy it is stored in a table with a Limit, Deductible, and Premium field. However, there are many coverages that do not follow the norm. They use different fields for Limit, Deductible, and Premium and are even stored in different tables. (Don’t ask why and don’t even try to understand the fact that they are STILL doing this so I need to leave logic to allow for additional coverages like this.) There is also no rhyme or reason to what fields they choose so varies greatly.
So, we have decided to create “LookUp” tables that will store all the information we need for a coverage. This avoids numerous joins – we were having issues with speed and performance of the application.
I need to find a way to prepopulate all these fields into a table. I would like the best option performance-wise. This will end up being a Nightly job – so when we receive a new snapshot of data we will run this query and prepopulate/update the values of the table.
I have the following code, I loop through this for each policy, essentially 614,000 time each night...It takes a LONG time to run.
Is there a better way for me to do this?
SELECT #SQL = N'SELECT #Limit=' + ISNULL(Limit, '''''') + N',#Deductible=' + ISNULL(Deductible, '''''') + N',#Premium=' + ISNULL(Premium, '''''') + N' FROM PHI_PIJ.dbo.ASBYCPP' + N' WHERE ' + PolicyNum + N' = ''' + #PolicyKey +'''' + N' AND BYAOTX' + N'='''+Coverage +''''
FROM PolicySummary.dbo.Coverage
WHERE Coverage = #Coverage
AND LOB = 'BOP'
EXEC sp_executesql #SQL, N'#Limit nVarChar(255) output,#Deductible nVarChar(255) output,#Premium nVarChar(255) output', #Limit output, #Deductible output, #Premium output
UPDATE PolicySummary.dbo.CoverageLkup
SET Limit = #Limit, Deductible = #Deductible, Premium = #Premium
WHERE CovAbbrev = #Coverage
AND PolicyKey = #PolicyKey
Here is what is inside my While Loop:
SELECT #SQL = N'SELECT #Limit=' + ISNULL(Limit, '''''') + N',#Deductible=' + ISNULL(Deductible, '''''') + N',#Premium=' + ISNULL(Premium, '''''') + N' FROM PHI_PIJ.dbo.' + [File] + N' WHERE ' + PolicyNum + N' = ''' + #PolNum +'''' + N' AND ' + #CovField + N'='''+Coverage +''''
FROM PolicySummary.dbo.Coverage
WHERE Coverage = #Coverage
AND LOB = #LOB
EXEC sp_executesql #SQL, N'#Limit nVarChar(255) output,#Deductible nVarChar(255) output,#Premium nVarChar(255) output', #Limit output, #Deductible output, #Premium output
INSERT INTO #OptCov2 VALUES(#Coverage, #Description, #LOB, #Limit, #Deductible, #Premium)
Related
Azure SQL Server 2017 -
We have a table dbo.MailArchive with a field called Mail_Body which contains the body of an email. The data always looks like this from record to record, just with different numbers, and Status message:
Status: Completed
Successful actions count: 250
Page load count: 250
But copy/pasting the above to test with will make it seem like there's no issue. YOu can use this to replicate the problem:
DECLARE #YourString varchar(8000) = 'Status: Completed
Successful actions count: 250
Page load count: 250' + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10);
SELECT CONCAT('{"', REPLACE(REPLACE(#YourString, ': ', '":"'), CHAR(13) + CHAR(10), '","'), '"}')
Further, this is what the body of the email looks like if I view it in Word with hidden characters turned on:
This is the format that the data gets exported to the database in.
I'm trying to use OPENJSON to parse this data by line break, as such:
SELECT Mail_Body,
j.*
FROM dbo.MailArchive d
CROSS APPLY OPENJSON (CONCAT('{"', REPLACE(REPLACE(d.Mail_Body, ': ', '":"'), CHAR(13) + CHAR(10), '","'), '"}'))
WITH (
Status varchar(100) '$.Status',
Successful_Actions_Count int '$."Successfull actions count"',
Request_Count int '$."Request count"'
) j
I get the following error when executing this:
JSON text is not properly formatted. Unexpected character ',' is found
at position 246.
Based on some advice I've received thus far, I'm thinking it might have something to do with that line break at the end of the body. But I can't figure out the right syntax to account for it.
This is an expensive fix, as REVERSE isn't cheap, but you could use it and PATINDEX to find the first characters that aren't a line break or carriage return, remove them, and then parse that:
DECLARE #YourString varchar(8000) = 'Status: Completed
Successful actions count: 250
Page load count: 250' + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10);
DECLARE #PI varchar(7) = '%[^' + CHAR(13) + CHAR(10) + ']%';
SELECT j.Status,
j.Successful_Actions_Count, --NULL as not in sample data
j.Request_Count --NULL as not in sample data
FROM (VALUES(#YourString))V(YS)
CROSS APPLY(VALUES(REVERSE(V.YS),PATINDEX(#PI,REVERSE(V.YS)))) PI(SY,I)
CROSS APPLY(VALUES(REVERSE(STUFF(PI.SY,1,PI.I,''))))S(FixedString)
CROSS APPLY OPENJSON (CONCAT('{"', REPLACE(REPLACE(S.FixedString, ': ', '":"'), CHAR(13) + CHAR(10), '","'), '"}'))
WITH (Status varchar(100) '$.Status',
Successful_Actions_Count int '$."Successfull actions count"',
Request_Count int '$."Request count"') j;
This assumes that there could be 0 to many sets of CHAR(13) + CHAR(10) at the end of the string. If it is only ever 2 sets, simply using SUBSTRING and LEN would be easier.
I have created a DB Mail alert that sends out a HTML formatted table showing the pass or fail status of my SQL agents.
The alert works well, but the user has request an additional change where they want conditional formating on Pass/Fail status of the data, where failed status is to be highlighted RED and pass status to be highlighted GREEN.
Is this possible to achieve to in SQL using DB Mail and HTML formatting?
A few forums have stated that JavaScript may need to be used but I'm not sure if its possible to even us JS in SQL.
My code is below:
----------------------------------------------------------------------------
----------------------------------- Declare Variables ----------------------
----------------------------------------------------------------------------
Declare #email_body nvarchar(max)
Declare #email_profile_name nvarchar(max)
Declare #email_recipients nvarchar(max)
Declare #email_subject nvarchar(max)
Declare #tableHTML nvarchar(MAX) = ''
Declare #Style nvarchar(MAX) = ''
Declare #Textdate nvarchar(max)
DECLARE #crlf nvarchar = CHAR(13)+CHAR(10)
Declare #Server nvarchar(max)
----------------------------------------------------------------------------
--------------------------- Set Varriables (That should not change) --------
----------------------------------------------------------------------------
set #Server = ##SERVERNAME
set #Textdate = cast(getdate() as date)
Set #email_subject = #Textdate + ': Morning SQL Server Checks'
----------------------------------------------------------------------------
----------------------------------- Set Varriables (User Input) ------------
----------------------------------------------------------------------------
--Add other Email addresses as needed. Seperate with Semi-colon (;)
set #email_recipients = 'Email#Email.com'
----------------------------------------------------------------------------
----------------------------------- Create Temp Tables ---------------------
----------------------------------------------------------------------------
IF OBJECT_ID('tempdb..#Results') IS NOT NULL
DROP TABLE #Results
Create table #Results (
[Server] nvarchar(max),
[Entity] nvarchar(max),
[Status] nvarchar(max),
[Message] nvarchar(max),
[Type] nvarchar(max))
----------------------------------------------------------------------------
----------------------------------- Generate Data --------------------------
----------------------------------------------------------------------------
--Gets SQL Agent Results (Script Derived from here:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/534cc5be-0021-4766-
9eef-92fea819e2e3/script-to-get-sql-server-agent-job-schedule-and-the-last-
run-status?forum=sqldatabaseengine)
Insert into #Results
SELECT ##SERVERNAME as 'Server Name'
,J.Name AS 'Job Name'
--,CASE J.Enabled WHEN 1 THEN 'Yes' WHEN 0 THEN 'No' END as 'Job
Enabled'
,CASE WHEN LASTRUN.run_status = 0 THEN 'Failed'
WHEN LASTRUN.run_status = 1 THEN 'Succeeded'
WHEN LASTRUN.run_status = 2 THEN 'Retry'
WHEN LASTRUN.run_status = 3 THEN 'Cancelled'
ELSE 'Unknown' END as 'Last Run Status'
,LASTRUN.message as 'Last Run Message'
,'SQL Agent Jobs' as 'Type'
FROM msdb.dbo.sysjobs J LEFT OUTER JOIN msdb.dbo.sysjobschedules JS ON
J.job_id = JS.job_id
LEFT OUTER JOIN msdb.dbo.sysschedules S ON JS.schedule_id = S.schedule_id
LEFT OUTER JOIN (SELECT J1.job_id
,J1.RUN_DURATION
,J1.run_date
,J1.run_time
,J1.message
,J1.run_status
FROM msdb.dbo.sysjobhistory J1
WHERE instance_id = (SELECT MAX(instance_id)
FROM msdb.dbo.sysjobhistory J2
WHERE J2.job_id = J1.job_id)) LASTRUN ON J.job_id = LASTRUN.job_id
where J.Enabled = 1 --Only check for agents that have been enabled
--------------------------------------------------------------------------
----------------------------------- Generate Email -------------------------
----------------------------------------------------------------------------
--Set Style (CSS)
SET #Style += +N'<style type="text/css">' + N'.tg {border-
collapse:collapse;border-spacing:0;border-color:#aaa;}'
+ N'.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#333;background-color:#fff;}'
+ N'.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#fff;background-color:#f38630;}'
+ N'.tg .tg-9ajh{font-weight:bold;background-color:#68cbd0}' + N'.tg .tg-hgcj{font-weight:bold;text-align:center}'
+ N'</style>';
--Set Email Output (HTML Layout)
Set #tableHTML += #Style + #tableHTML + N'<H1 style="color:Blue;">' +
#Textdate + ': Morning SQL Server Checks</H1>' +
N'<H2>' + #Server + '</H2>' +
N'<H3>Databases</H3>' +
+ N'<table class="tg">' --DEFINE TABLE
-- Define Headers for Database Check
+ N'<tr>'
+ N'<H3>SQL Agents</H3>' +
+ N'<table class="tg">' --DEFINE TABLE
+ N'<tr>'
+ N'<td class="tg-9ajh">Server</td>'
+ N'<td class="tg-9ajh">Entity</td>'
+ N'<td class="tg-9ajh">Status</td>'
+ N'<td class="tg-9ajh">Message</td>'
+ N'<td class="tg-9ajh">Type</td></tr>'
-- Define data for SQL Agent and cast to xml
+ Cast((
Select td = isnull([Server],'###')
,''
,td = isnull([Entity],'###')
,''
,td = isnull([Status],'###')
,''
,td = isnull([Message],'###')
,''
,td = isnull([Type],'###')
,''
from #Results
where [type] = 'SQL Agent Jobs' FOR
XML PATH('tr') ,
TYPE
) AS NVARCHAR(MAX))
+ N'</table>';
-- Send the Email
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Outlook Support Profile',
#recipients = #email_recipients,
#body = #tableHTML,
#body_format = 'HTML',
#subject = #email_subject
----------------------------------------------------------------------------
----------------------------------- Cleanup --------------------------------
----------------------------------------------------------------------------
drop table #Results
I hope the code is clear enough and makes sense.
Thanks you
Anthony
I do something similar with my dbmail audit emails to differentiate between production and non-production instances.
The method I use is to predefine the style information and then use a unique value in the body string to identify where the style needs to be applied. In your case the unique values we can use are <td>Failed and <td>Succeeded. By doing a replace on those values to a version that includes the style, you should get a table with your conditional formatting.
I made the following two changes to your script and ran it against one of my test instances. It looks like it should get you where you want.
First, update the style section:
--Set Style (CSS)
SET #Style += +N'<style type="text/css">' + N'.tg {border-
collapse:collapse;border-spacing:0;border-color:#aaa;}'
+ N'.tg .green{background-color: green; color:white;}'
+ N'.tg .red{background-color: red; color:white;}'
+ N'.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#333;background-color:#fff;}'
+ N'.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#aaa;color:#fff;background-color:#f38630;}'
+ N'.tg .tg-9ajh{font-weight:bold;background-color:#68cbd0}' + N'.tg .tg-hgcj{font-weight:bold;text-align:center}'
+ N'</style>';
After #tableHTML is built, add a REPLACE to shove the style formatting into the generated table:
SELECT #tableHTML = REPLACE(REPLACE(#tableHTML,N'<td>Failed',N'<td class="Red">Failed'),N'<td>Succeeded',N'<td class="green">Succeeded')
Are there any scripts available to migrate SQL Server users from SQL Server 2008 to SQL Server 2008 R2 along with the User Mappings, Roles and permissions please?
I am following
https://support.microsoft.com/en-us/help/918992/how-to-transfer-logins-and-passwords-between-instances-of-sql-server
But the instructions in that link just assists in migrating the users.
The user mappings, roles and permissions don't get migrated.
Apologies if such question was already answered.
I had a quick search, but could not find a solution to my issue.
Thanks
Does this work?
/****** Object: StoredProcedure [dbo].[usp_get_object_permissions] Script Date: 10/07/2011 14:28:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- run this script from the user database
--exec usp_get_object_permissions
--drop proc usp_get_object_permissions
--go
CREATE PROCEDURE [dbo].[usp_get_object_permissions]
AS
set nocount on
set quoted_identifier off
declare #as_ObjectName sysname
set #as_ObjectName = NULL
--database owner info
select 'alter authorization on database::['+db_name()+'] to ['+ suser_sname(owner_sid)+']'
AS '--owner of database when script was created'
from master.sys.databases where name = db_name()
--drop and recreate users
select '-- It is not always necessary to drop and recreate the users it will depend on the circumstances under which you need to run this script'
select 'drop user [' + name + ']' from sys.database_principals
where principal_id > 4 and owning_principal_id is NULL
and type != 'A'
order by name
select 'CREATE USER [' + dp.name collate database_default + '] FOR LOGIN [' + sp.name + ']'+
case dp.type
when 'G' then ' '
else
' WITH DEFAULT_SCHEMA=['+dp.default_schema_name + ']'
end
as '-- by default Orphaned users will not be recreated'
from sys.server_principals sp
inner join sys.database_principals dp on dp.sid = sp.sid
where dp.principal_id > 4 and dp.owning_principal_id is NULL and sp.name <> ''
order by dp.name
-- Recreate the User defined roles
select '-- server created roles should be added by the correct processes'
select 'CREATE ROLE ['+ name + '] AUTHORIZATION ['+USER_NAME(owning_principal_id)+']'
from sys.database_principals
where name != 'public' and type = 'R' and is_fixed_role = 0
-- recreate application roles
select 'CREATE APPLICATION ROLE ['+ name + '] with password = '+QUOTENAME('insertpwdhere','''')+' ,default_schema = ['+default_schema_name+']'
from sys.database_principals
where type = 'A'
-- ADD ROLE MEMBERS
SELECT 'EXEC sp_addrolemember [' + dp.name + '], [' + USER_NAME(drm.member_principal_id) + '] ' AS [-- AddRolemembers]
FROM sys.database_role_members drm
INNER JOIN sys.database_principals dp ON dp.principal_id = drm.role_principal_id
where USER_NAME(drm.member_principal_id) != 'dbo'
order by drm.role_principal_id
-- CREATE GRANT Object PERMISSIONS SCRIPT
SELECT replace(state_desc,'_with_grant_option','') + ' '+ permission_name + ' ON ['
+ OBJECT_SCHEMA_NAME(major_id) + '].[' + OBJECT_NAME(major_id) + ']'+
case minor_id
when 0 then ' '
else
' (['+col_name(sys.database_permissions.major_Id, sys.database_permissions.minor_id) + '])'
end
+' TO [' + USER_NAME(grantee_principal_id)+']' +
case
when state_desc like '%with_grant_option' then ' with grant option'
else
' '
end
as '-- object/column permissions'
FROM sys.database_permissions (NOLOCK)
WHERE class not in (0,3) and major_id = ISNULL(OBJECT_ID(#as_ObjectName), major_id)
--AND OBJECT_SCHEMA_NAME(major_id) != 'SYS'
ORDER BY USER_NAME(grantee_principal_id),OBJECT_SCHEMA_NAME(major_id), OBJECT_NAME(major_id)
--SCHEMA permissions
SELECT replace(state_desc,'_with_grant_option','') + ' '+ permission_name + ' ON SCHEMA::['
+ SCHEMA_NAME(major_id) + ']'+
+' TO [' + USER_NAME(grantee_principal_id)+']' +
case
when state_desc like '%with_grant_option' then ' with grant option'
else
' '
end
as '-- Schema permissions'
FROM sys.database_permissions (NOLOCK)
WHERE class_desc = 'SCHEMA'
ORDER BY USER_NAME(grantee_principal_id),SCHEMA_NAME(major_id)
SELECT replace(state_desc,'_with_grant_option','') + ' '+ permission_name +
' TO [' + USER_NAME(grantee_principal_id)+']' +
case
when state_desc like '%with_grant_option' then ' with grant option'
else
' '
end
FROM sys.database_permissions (NOLOCK)
WHERE permission_name = 'VIEW DEFINITION' and class_desc = 'database'
ORDER BY USER_NAME(grantee_principal_id)
I have a SQL Server 2014 database from which I need to dump just the table data (no indexes, stored procedures, or anything else).
This dump needs to be imported into a Postgres 9.3 database "as-is".
What id the proper command line to create such a dump?
I must admit, this is more sort of a joke... You should rather follow the hint to use "Export" and write this to some kind of CSV. Just for fun:
EDIT: create a column list to avoid binary columns...
columns, which are not directly convertible into XML RAW are added with "invalid data":
DECLARE #Commands TABLE(ID INT IDENTITY,cmd NVARCHAR(MAX));
INSERT INTO #Commands(cmd)
SELECT '(SELECT TOP 3 '
+ STUFF(
(
SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS AS c
WHERE c.TABLE_CATALOG=t.TABLE_CATALOG AND c.TABLE_SCHEMA=t.TABLE_SCHEMA AND c.TABLE_NAME=t.TABLE_NAME
AND c.DATA_TYPE NOT IN('image','text') AND c.DATA_TYPE NOT LIKE '%BINARY%'
FOR XML PATH('')
),1,1,''
)
+
(
SELECT ',''invalid data'' AS ' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS AS c
WHERE c.TABLE_CATALOG=t.TABLE_CATALOG AND c.TABLE_SCHEMA=t.TABLE_SCHEMA AND c.TABLE_NAME=t.TABLE_NAME
AND (c.DATA_TYPE IN('image','text') OR c.DATA_TYPE LIKE '%BINARY%')
FOR XML PATH('')
)
+ ' FROM ' + QUOTENAME(t.TABLE_CATALOG) + '.' + QUOTENAME(t.TABLE_SCHEMA) + '.'
+ QUOTENAME(t.TABLE_NAME) + ' FOR XML RAW,TYPE) AS ' + QUOTENAME(t.TABLE_CATALOG + '_' + t.TABLE_SCHEMA + '_' + t.TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES AS t WHERE t.TABLE_TYPE='BASE TABLE';
DECLARE #finalCommand NVARCHAR(MAX)=
(
SELECT 'SELECT '
+'(SELECT TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES FOR XML RAW,TYPE) AS ListOfTables'
+ (
SELECT ',' + cmd
FROM #Commands
ORDER BY ID
FOR XML PATH('')
)
+ ' FOR XML PATH(''AllTables'')'
);
EXEC( #finalCommand);
Microsoft recently announced a new command line tool mssql-scripter (it's open source and multi-OS) that allows you to generate T-SQL scripts for databases/database objects as a .sql file. The announcement is here.
Once launching the scripter you'll want to run a command similar to the following:
$ mssql-scripter -S serverName -U userName -d databaseName --data-only
More details are on the GitHub page usage guide: https://github.com/Microsoft/sql-xplat-cli/blob/dev/doc/usage_guide.md
How can I parameterize the following query? (By the way I'm using a full text indexed table, hence the CONTAINS())
SELECT * FROM Table WHERE CONTAINS(Column, 'cat OR dog')
and ((column NOT LIKE '%[^ cat OR dog]%'));
This didn't work:
DECLARE #term1 VARCHAR(10);
DECLARE #term2 VARCHAR(10);
SET #term1 = 'cat';
SET #term2 = 'dog';
SET #term3 = #term1 + ' ' + 'OR' + ' ' + #term2;
SET #term4 = '[^ #term1 OR #term2 ]' ;
SELECT * FROM table WHERE CONTAINS(column, #term3) <--up to this point works
AND (column NOT LIKE '%[#term4]%'); <--this part doesn't include the second term (#term2)
If you'd like to fiddle with this on your end, my Full Text Indexed table looks like:
animalListID AnimalsList
1 cat dog
2 cat
3 cat dog bird
(basically i need the parameterized version of the SELECT statement which returns the rows with 'cat dog' and 'cat' and NOT 'cat dog bird')
**This is a VERY oversimplified version of my data, but the question is an exact match of the concept I'm trying to achieve. The table will have millions of rows, and many terms in each row.
You should do
SET #term4 = '[^ ' + #term1 + ' OR ' + #term2 + ' ]';
and
column NOT LIKE '%' + #term4 + '%'
Alternatively, you could initialize #term4 to also include the % signs:
SET #term4 = '%[^ ' + #term1 + ' OR ' + #term2 + ' ]%';
and then simplify the LIKE statement to:
column NOT LIKE #term4