<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Using a SAS transaction dataset to delete records from SQL Server table in SAS Data Management</title>
    <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425542#M13103</link>
    <description>&lt;P&gt;Sorry for being unclear.&lt;/P&gt;
&lt;P&gt;Say you want to create a SAS table from SQL server table and your SQL server table is temporary one, then it is slow. Instead of temporary table if you&amp;nbsp;c&lt;SPAN&gt;reate a SAS table from SQL&lt;/SPAN&gt; a permanent table, it is often much faster. This property I have observed many times both in SQL server and Teradata, especially at my last client location.&lt;/P&gt;</description>
    <pubDate>Sat, 06 Jan 2018 22:34:49 GMT</pubDate>
    <dc:creator>kiranv_</dc:creator>
    <dc:date>2018-01-06T22:34:49Z</dc:date>
    <item>
      <title>Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425353#M13095</link>
      <description>&lt;P&gt;I have a SQL server master table, and a SAS dataset of transactions which are deletions to be applied.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks to some advice from &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/15043"&gt;@ScottBass&lt;/a&gt;&amp;nbsp;in &lt;A href="https://communities.sas.com/t5/General-SAS-Programming/Can-I-update-a-SQL-Server-table-in-place-using-the-modify/td-p/316149" target="_blank"&gt;https://communities.sas.com/t5/General-SAS-Programming/Can-I-update-a-SQL-Server-table-in-place-using-the-modify/td-p/316149&lt;/A&gt;, I've made progress.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I upload my transaction dataset to SQL server, then use explicit pass through to execute the SQL server MERGE statement.&amp;nbsp; My code looks like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;***Setup ;

*SQL master table (sql libref points to sql server database);
data sql.qMaster ;
  do id1=1 to 10 ;
    do id2= 1 to 5 ;
      output ;
    end ;
  end ;
run ;

*SAS transaction dataset of records to delete from the SQL data ;
data qTrans ;
  do id1=3,6,9 ;
    do id2=3,4 ;
      output ;
    end ;
  end ;
run ;


*PROC SQL to upload transaction table to SQL, then execute the  SQL server merge;

proc sql;
  create table sql.qTrans as
    select * from qTrans 
  ;      
 
  connect to ODBC as myconn
    (datasrc=... user=... password="...");
  ;

  execute (
    merge qMaster 
    using qTrans
    on (qMaster.id1=qTrans.id1 and qMaster.id2=qTrans.id2)
    when matched then delete 
    ;
  ) by myconn ;

  disconnect from myconn ;
quit ;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It looks like that is doing what I want.&amp;nbsp; I feel like when I upload qTrans to SQL server I should make it a temporary table, but I couldn't get it to work.&amp;nbsp; I tried e.g. create table sql.'#qTrans'n but couldn't get it to work.&amp;nbsp; And I don't know anything about SQL server temp tables, would #qTrans persist long enough to be seen by my execute statement?&amp;nbsp; What about if I made it ##qTrans?&amp;nbsp; I suppose I don't have much to gain by making it an official temporary table rather than just dropping qTemp at the end, but figured it's worth a shot&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Any other recommendations for improvements to this approach?.&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jan 2018 20:07:09 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425353#M13095</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2018-01-05T20:07:09Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425358#M13097</link>
      <description>Have you read this?&lt;BR /&gt;&lt;A href="http://support.sas.com/documentation/cdl/en/acreldb/65247/HTML/default/viewer.htm#p1h2yn2en7gkb8n1mba66mxgnf56.htm" target="_blank"&gt;http://support.sas.com/documentation/cdl/en/acreldb/65247/HTML/default/viewer.htm#p1h2yn2en7gkb8n1mba66mxgnf56.htm&lt;/A&gt;</description>
      <pubDate>Fri, 05 Jan 2018 20:16:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425358#M13097</guid>
      <dc:creator>LinusH</dc:creator>
      <dc:date>2018-01-05T20:16:05Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425374#M13098</link>
      <description>&lt;P&gt;Adding to&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13674"&gt;@LinusH&lt;/a&gt;&amp;nbsp;both&amp;nbsp; temporary tables are for a session. only difference # and ## is , ## tables are global temp tables, which are available to all the users where #tables are local ones, which are available only to the user.&amp;nbsp; There is no performance enhancement for either.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;of the topic,&amp;nbsp; huge performance impacts are often seen when data is moved from temporary dbms to SAS as opposed to data movement from Permanent dbms table to SAS. to conclude, Moving a volatile/temporary DBMS table to SAS is very slow.&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jan 2018 20:44:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425374#M13098</guid>
      <dc:creator>kiranv_</dc:creator>
      <dc:date>2018-01-05T20:44:46Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425539#M13102</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/37783"&gt;@kiranv_&lt;/a&gt;&amp;nbsp;can you explain your second paragraph? I can't understand it.&amp;nbsp; Are you saying that the process of using SAS/ACCESS to read from a SQL server temporary table is faster/slower than reading from a SQL server permanent table?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks for the explanation of # vs ##.&amp;nbsp; That helps.&lt;/P&gt;</description>
      <pubDate>Sat, 06 Jan 2018 22:19:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425539#M13102</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2018-01-06T22:19:36Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425542#M13103</link>
      <description>&lt;P&gt;Sorry for being unclear.&lt;/P&gt;
&lt;P&gt;Say you want to create a SAS table from SQL server table and your SQL server table is temporary one, then it is slow. Instead of temporary table if you&amp;nbsp;c&lt;SPAN&gt;reate a SAS table from SQL&lt;/SPAN&gt; a permanent table, it is often much faster. This property I have observed many times both in SQL server and Teradata, especially at my last client location.&lt;/P&gt;</description>
      <pubDate>Sat, 06 Jan 2018 22:34:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425542#M13103</guid>
      <dc:creator>kiranv_</dc:creator>
      <dc:date>2018-01-06T22:34:49Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425553#M13104</link>
      <description>&lt;P&gt;Thanks &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13674"&gt;@LinusH&lt;/a&gt;&amp;nbsp;and &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/37783"&gt;@kiranv_&lt;/a&gt;.&amp;nbsp; I hadn't seen that page of the docs.&amp;nbsp; Looks like adding connection=shared to the libname statement was the key.&amp;nbsp; And I had to use ##tableNames to get it to work.&amp;nbsp; I suspect it's because I use implicit pass through to write the SAS transaction table to SQL server, then use explicit pass through to execute the MERGE statement.&amp;nbsp; So I suppose to SQL, I may be two different sessions.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Looks like below works:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;libname sql odbc dsn= user="..." password="..." schema=dbo connection=shared;

data sql.qMaster (insertbuff=1000);
  do id1=1 to 10 ;
    do id2= 1 to 5 ;
      output ;
    end ;
  end ;
run ;


*SAS dataset of records to delete from the SQL data ;
data qTrans ;
  do id1=3,6,9 ;
    do id2=3,4 ;
      output ;
    end ;
  end ;
run ;


proc sql;

  *upload work.qTrans to SQL server as temporary table ;
  create table sql.'##qTrans'n (insertbuff=1000) as
    select * from qTrans 
  ;      
 
  connect to ODBC as myconn
    (datasrc="" user= password="");
  ;

  execute (
    merge qMaster 
    using ##qTrans
    on (qMaster.id1=##qTrans.id1 and qMaster.id2=##qTrans.id2)
    when matched then delete 
    ;
    drop table ##qTrans  ;
  ) by myconn ;

  disconnect from myconn ;

  create table want as 
  select * from sql.qMaster 
  ;
quit ;

libname sql clear ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Still happy to hear any suggested improvements.&lt;/P&gt;</description>
      <pubDate>Sun, 07 Jan 2018 00:21:55 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/425553#M13104</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2018-01-07T00:21:55Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/427590#M13173</link>
      <description>&lt;P&gt;I was in the midst of replying to the OP by &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;when the solution(s) were posted.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, since I put some work into this, here goes, apologies if some of this is redundant...&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;First of all, have a look at &lt;A href="https://www.red-gate.com/simple-talk/sql/t-sql-programming/temporary-tables-in-sql-server" target="_self"&gt;https://www.red-gate.com/simple-talk/sql/t-sql-programming/temporary-tables-in-sql-server&lt;/A&gt;/.&amp;nbsp; It's a bit long, but goes into details about temp tables and table variables.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Second, do this in SQL Server Management Studio:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1)&amp;nbsp;In query window #1:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;SELECT name, database_id INTO tempdb.dbo.table1 FROM master.sys.databases&lt;BR /&gt;SELECT name, database_id INTO #table2 FROM master.sys.databases &lt;BR /&gt;SELECT name, database_id INTO ##table3 FROM master.sys.databases&lt;BR /&gt;&lt;BR /&gt;SELECT * FROM tempdb.INFORMATION_SCHEMA.Tables WHERE table_name LIKE '%table%'&lt;BR /&gt;&lt;BR /&gt;SELECT * FROM tempdb.dbo.table1&lt;BR /&gt;SELECT * FROM #table2&lt;BR /&gt;SELECT * FROM ##table3&lt;/PRE&gt;&lt;P&gt;2) In a second query window:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;SELECT * FROM tempdb.INFORMATION_SCHEMA.Tables WHERE table_name LIKE '%table%'

SELECT * FROM tempdb.dbo.table1
SELECT * FROM ##table3 
SELECT * FROM #table2&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In the 2nd query window, you can see that table1, #table2, and ##table3 &lt;U&gt;exist&lt;/U&gt;, but you can only &lt;U&gt;access&lt;/U&gt; table1 and ##table3; #table2 can only be accessed by the process ID that created it.&amp;nbsp; (You can submit SELECT&amp;nbsp;@@spid to get the process ID, but it's also displayed next to your userid in SSMS).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Now, close the first query window, and resubmit the code in the second query window.&amp;nbsp; You'll see that #table2 and ##table3 have disappeared.&amp;nbsp; So, the Temporary Tables persist only for the life of the process ID that created them, and global temporary tables can be accessed by other process ID's, but again &lt;STRONG&gt;*they only exist during the life of the process ID that created them*.&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;With that in mind, submit the below code in SAS EG (modify as required).&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* set desired SAS options ;
options sastrace=',,,d' sastraceloc=saslog nostsuffix;
options msglevel=I;
options fullstimer;
options mprint mrecall;
options compress=binary;
options ls=max;
options nocenter;
options lognumberformat=1;

libname TMP odbc NOPROMPT="Driver={SQL Server Native Client 10.0};Server=XXXXXXXX;Database=TempDB;Trusted_Connection=yes;" bulkload=yes schema=dbo ;

* #1A ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO tempdb.dbo.table1 FROM master.sys.databases;
   );
   select * from connection to tmp (
      SELECT * FROM tempdb.dbo.table1;
   );
   execute by tmp (
      DROP TABLE tempdb.dbo.table1;
   );
quit;

* #1B ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO tempdb.dbo.table1 FROM master.sys.databases;
   );
quit;

proc sql;
   connect using tmp;
   select * from connection to tmp (
      SELECT * FROM tempdb.dbo.table1;
   );
   execute by tmp (
      DROP TABLE tempdb.dbo.table1;
   );
quit;

* #2A ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO #table2 FROM master.sys.databases;
   );
   select * from connection to tmp (
      SELECT * FROM #table2;
   );
   execute by tmp (
      DROP TABLE #table2;
   );
quit;

* #2B ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO #table2 FROM master.sys.databases;
   );
quit;

proc sql;
   connect using tmp;
   select * from connection to tmp (
      SELECT * FROM #table2;
   );
   execute by tmp (
      DROP TABLE #table2;
   );
quit;

* #3A ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO ##table3 FROM master.sys.databases;
   );
   select * from connection to tmp (
      SELECT * FROM ##table3;
   );
   execute by tmp (
      DROP TABLE ##table3;
   );
quit;

* #3B ;
proc sql;
   connect using tmp;
   execute by tmp (
      SELECT name, database_id INTO ##table3 FROM master.sys.databases;
   );
quit;

proc sql;
   connect using tmp;
   select * from connection to tmp (
      SELECT * FROM ##table3;
   );
   execute by tmp (
      DROP TABLE ##table3;
   );
quit;

* #4 ;
proc sql;
   connect using tmp;

   create table tmp.'#class2'n as
   select * from sashelp.class;

   select * from connection to tmp (
      SELECT * FROM #class2;
   );
   execute by tmp (
      DROP TABLE #class2;
   );
quit;

* #5 ;
proc sql;
   connect using tmp;

   create table tmp.'##class3'n as
   select * from sashelp.class;

   select * from connection to tmp (
      SELECT * FROM ##class3;
   );
   execute by tmp (
      DROP TABLE ##class3;
   );
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;My conclusion is that the connections from SAS to SQL Server are transient, with each connection resulting in a new process ID.&amp;nbsp; This is then problematic for the reasons above.&amp;nbsp; Furthermore, global temporary tables can have security issues if the data is sensitive.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;After pulling out my hair a few times trying to make temporary tables "work", my usual approach has been to create a "tmp" schema in my database, writing "temporary" tables to the tmp schema, and dropping the tables once I'm done with them.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Hope this helps...&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 15 Jan 2018 02:16:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/427590#M13173</guid>
      <dc:creator>ScottBass</dc:creator>
      <dc:date>2018-01-15T02:16:07Z</dc:date>
    </item>
    <item>
      <title>Re: Using a SAS transaction dataset to delete records from SQL Server table</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/427696#M13188</link>
      <description>&lt;P&gt;Thanks &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/15043"&gt;@ScottBass&lt;/a&gt;, that helps a lot in understanding how SQL server temp tables work.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And as so often happens in forums like this, in addressing my main question you showed me something unrelated which will be a huge benefit to me.&amp;nbsp; I haven't seen the connect USING &amp;lt;libref&amp;gt; syntax before. That is a lovely thing!&amp;nbsp; Apparently introduced in 9.3, so I'm only about six years late to the party... : )&amp;nbsp;&amp;nbsp; &lt;A href="https://philihp.com/blog/2012/reusing-a-libnames-database-connection-in-pass-through/" target="_blank"&gt;https://philihp.com/blog/2012/reusing-a-libnames-database-connection-in-pass-through/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 15 Jan 2018 14:19:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Using-a-SAS-transaction-dataset-to-delete-records-from-SQL/m-p/427696#M13188</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2018-01-15T14:19:08Z</dc:date>
    </item>
  </channel>
</rss>

