SQL - WHERE statement with text added to value from table - sql-server

I need to copy data from an old database to a newer one.
Both of these databases have a user setup table with the primary key of "USER ID".
The problem is, in the old database the users didn't have the domain in the name, but in the new one they have.
Example:
Primary Key old DB: USER1
Primary Key new DB: DOMAIN\USER1
This prevents a standard WHERE clause to update the correct user because it can't find it due to the domain being added.
My code:
'FROM [' + #src_DB + '].dbo.[' + #src_table + '] as src '
'WHERE [' + #dest_DB + '].dbo.[' + #dest_table + '].[User ID] = ' + #domain_name + 'src.[User ID]'
printing the result:
WHERE [Destination_DB].dbo.[Destination_Table].[User ID] = DOMAIN\src.[User ID]
The problem is it doesn't add the DOMAIN to the value but rather to the statement...
How can I add the Domain to the actual value of src.[User ID]?

I think there's a dot missing, and you should use QUOTENAME
'WHERE ' + QUOTENAME(destination_table) + '.[User ID] = ' + QUOTENAME(#domain) + '.' + QUOTENAME(source_table) + '.[User ID]'
Whenever you create a SQL statement dynamically it's a good idea to print it out, copy it into a new query window and check for syntax errors...
UPDATE You: Yes, both databases are in the same server
An object can be (fully) specified with
ServerName.DatabaseName.Schema.ObjectName
A table's column would add one more .ColumnName
When both objects live on the same server you can let the first part away.
Objects of the same database let this part away.
Objects of the default schema might be called with the ObjectName alone.
But if you state a DatabaseName you must also state a SchemaName!
Use QUOTENAME() to add the brackets and add just the dots via string concatenation (or use CONCAT()-function).
UPDATE 2 Did I get this wrong completely?
After you comment I think I understand it now: You want to compare the values of both [USER ID] columns, but the new is DOMAIN\MyUserId while the older was just MyUserId.
You have two approaches
Add the Domain\ as string to the value of [User ID]
Use SUBSTRING([User ID],CHARINDEX('\',[UserID])+1,1000) to cut the newer value down to the naked value of [User ID]
For the first something like this
'WHERE [' + #dest_DB + '].dbo.[' + #dest_table + '].[User ID] = ''' + #domain_name + ''' + src.[User ID]'
The second is quite clumsy with dynamically created SQL...

Related

MultiLine Query in Snowflake Stored Procedure

I am trying to build one stored procedure in snowflake which will
i. Delete existing records from dimension table.
ii. Insert the records into the dimension table from corresponding materialized view.
iii. Once the data is inserted, record the entry into a config table.
First two are running fine, third one is not working, code below
Table DIM_ROWCOUNT
CREATE TABLE ANALYTICSLAYER.AN_MEDALLIA_P.DIM_ROWCOUNT
(
"TABLE_NAME" VARCHAR(500),
"VIEW_NAME" VARCHAR(500),
"TABLE_ROWCOUNT" VARCHAR(500) ,
"VIEW_ROWCOUNT" VARCHAR(500),
"LOADDATE" timestamp
)
The SP has parameter as SRC_TABLE_NAME which should be loaded for column : TABLE_NAME,
VIEW_NAME will be derived inside code.
TABLE_ROWCOUNT and VIEW_ROWCOUNT will be calculated within the code.
I need to have a multi line query for insertion.
How to create the insert statement multiline?
var config_details = `INSERT INTO DBNAME.SCHEMANAME.TABLENAME
SELECT '${VAR_TABLE_NAME}','${VAR_VIEW_NAME}','${VAR_TABLE_ROW_COUNT}','${VAR_VIEW_ROW_COUNT}',getdate();`
var exec_config_details = snowflake.createStatement( {sqlText: config_details} );
var result_exec_config_details = exec_config_details.execute();
result_exec_config_details.next();
Any help in appreciated.
I tend to write complex SQL statements in a javascript SP by appending each line/portion of text to the variable, as I find it easier to read/debug
Something like this should work (though I haven't tested it so there may be typos). Note that to get single quotes round each value I am escaping them in the code (\'):
var insert_DIM_ROWCOUNT = 'INSERT INTO DBNAME.TEST_P.DIM_ROWCOUNT ';
insert_DIM_ROWCOUNT += 'SELECT \'' + SRC_TABLE_NAME + '\', \'' + VIEW_NAME + '\', \'';
insert_DIM_ROWCOUNT += TABLE_ROWCOUNT + '\', \'' + VIEW_ROWCOUNT + '\', ';
insert_DIM_ROWCOUNT += GETDATE();
I then test this to make sure the SQL statement being created is what I want by adding a temporary line of code, after this, to just return the SQL string:
return insert_DIM_ROWCOUNT;
Once I'm happy the SQL is correct I then comment out/delete this line and let the SQL execute.

Using wildcards for column names in dynamic soql in apex

I have a scenario where my columns names can be of type genesis__prod__c/docgen__prod__c/lnd__prod__c,etc depending upon which package is using my solution package. Here genesis,docgen and are different product packages using my solution.
My solution needs to fetch any of these(genesis__prod__c/docgen__prod__c/lnd__prod__c) fields from there respective sObjects in there products.
I want to construct a generic query which will omit the namespace using a wildcard and only look for prod__c in specified sObject. With this, I don't have to hardcode any namespace in my query.
for eg., I don't want to form my query like this
String query = 'select Id,Name,docgen__CL_Product__c from '+ sObjectType + ' where id= \'' + appId + '\'';
List<sObject> runtimeDeterminedObject = Database.query(query+' LIMIT 1');
Here I have specifically mentioned docgen__CL_Product__c name to be fetched from a runtime resolved sObject name sObjectType w.r.t an appId
How can I form a query where I do not have to provide namespace docgen,genesis before prod__c. I do not want to write if-else for each product which can utilize my package.
Why don't you make the namespace a variable that gets appended to the query based on some condition? Not exactly what you're looking for, but I'm assuming there's some way to determine the environment and then based on that you can adjust the query dynamically:
String env = someCondition ? 'genesis__' : 'docgen__';
String query = 'select Id, Name, ' + env + 'CL_Product__c from '+ sObjectType + ' where id= \'' + appId + '\'';
List<sObject> runtimeDeterminedObject = Database.query(query+' LIMIT 1');

How to avoid data repetition insertion?

Recently I have posted a question, it contains some syntax error, now the code is running without error, thanks to #Arulkumar.
But now I am facing one more problem, data from excel sheet is storing properly on to SQL Server database, but when I press refresh button or if I go to that link again in my application, data is repeating in the database. Means again it is retrieving values from excel and storing same data again in the database.
How can I avoid data repetition. Can any one please help me to solve this issue? Code and excel sheet sample is there in the above mentioned link.
You need MERGE statement
request.query('MERGE [mytable] as target USING (SELECT SalesPersonID, TerritoryID FROM OPENROWSET(' +
'\'Microsoft.ACE.OLEDB.12.0\', \'Excel 12.0;Database=D:\\sample\\test\\data\\1540_OPENROWSET_Examples.xls;HDR=YES\', ' +
'\'SELECT SalesPersonID, TerritoryID FROM [SELECT_Example$]\')' +
' ) as source' +
' ON target.SalesPersonID = source.SalesPersonID' +
' WHEN MATCHED THEN UPDATE SET TerritoryID = source.TerritoryID' +
' WHEN NOT MATCHED THEN INSERT (SalesPersonID, TerritoryID) VALUES (source.SalesPersonID, source.TerritoryID);'
,function(err,recordset){
if(err) console.log(err)
It will update TerritoryID if there is already row with same SalesPersonID and insert row if there is no matches in mytable.
If you need join on both fields change this:
ON target.SalesPersonID = source.SalesPersonID
On this:
ON target.SalesPersonID = source.SalesPersonID AND target.TerritoryID = source.TerritoryID
And after that - remove this string because it doesn't need anymore:
'WHEN MATCHED THEN UPDATE SET TerritoryID = source.TerritoryID' +

Display file path of documents in Crystal Report

I have a crystal report that lists invoices and I would like to be able to show the file path of the invoices in another column of the report. The following query allows me to search for the documents based on their unique ID number. It then displays the file location of the one document I search for, however I would like to have this apply to all of the documents listed in the report. Can someone please help me out with this?
`DECLARE #entryID INT = 35793
SELECT dbo.toc.name AS DocumentName, dbo.doc.pagenum + 1 AS PageNum, dbo.vol.fixpath + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),1,2) + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),3,2) + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),5,2) + '\' +
CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2) + '.TIF' AS FullPathAndFilename
FROM dbo.doc
LEFT JOIN dbo.toc ON dbo.doc.tocid = dbo.toc.tocid
LEFT JOIN dbo.vol ON dbo.toc.vol_id = dbo.vol.vol_id
WHERE dbo.doc.tocid = #entryID
ORDER BY dbo.doc.pagenum`
The answer depends on how you currently retrieve data in the existing Crystal Report.
Option A: If your report data source is a "Command" (in other words you have written a SQL statement in the crystal report that retrieves the data you need), then you will want to modify that command to pull in this new information via a subquery. So for example if your current report SQL is something like "select x.* from foo as x", you would want it to be something like:
select x.*,
(SELECT dbo.vol.fixpath + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),1,2) + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),3,2) + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),5,2) + '\'
+ CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2)
+ '.TIF' AS FullPathAndFilename
FROM dbo.doc
LEFT JOIN dbo.toc ON dbo.doc.tocid = dbo.toc.tocid
LEFT JOIN dbo.vol ON dbo.toc.vol_id = dbo.vol.vol_id
WHERE dbo.doc.tocid = x.tocid //this line joining the new SQL to all report rows
)
from foo as x;
Option B: If instead you pull your data from Crystal using the join wizard, then it would probably be best to create a new view in your database that matches the SQL you provided (minus the last 2 lines), and then join your existing main report tables to this view in the Crystal join wizard.

Create word document from SQL Server Management Studio - 1 row per page (email templates for client to view)

Hey there I have a simple EmailTemplate table with three columns:
TemplateName
EmailSubject
EmailContent
I have a client that wants to review all the templates and I'd like to put them into a word document, 1 per page, in the order they are above e.g.
-------------- page 1 --------------
[[TemplateName]]
[[EmailSubject]]
[[EmailContent]]
...
...
...
[[EmailContent]]
-------------- page 2 --------------
[[TemplateName]]
[[EmailSubject]]
[[EmailContent]]
...
...
...
[[EmailContent]]
Does anyone one know of an easy way to do this from SQL Server Management Studio?
Cheers
Rob
Word has a mail merge function that can be used with csv data, I'd recommend that over any attempt to build the entire thing in sql.
I did some more searching, lot's of code solutions but nothing out-of-the-box in SSMS so I did some more fiddling and here's what I did to achieve this:
Set the query output to text
Set the Query -> Query Options -> Text to: no headings and Delimeter | (so it's easy to remove)
Added formatting to the query with Tabs CHAR(9) and Line Breaks CHAR(10) as follows:
SELECT
'Template Name:' + CHAR(9) + CHAR(9) + Name + CHAR(10) + CHAR(10),
'Email Subject:' + CHAR(9) + CHAR(9) + TemplateSubject + CHAR(10) + CHAR(10) + CHAR(10),
'Contents:' + CHAR(10) + CHAR(10),
TemplateContent + CHAR(10) + CHAR(10) + CHAR(10) + CHAR(10) + '------------------------------------' FROM dbo.EmailTemplate
I just copy/paste this contents into Word and then went through and converted the dashed line "----" to page breaks and sent it off to the client to review.

Resources