SAS - Overwriting a dataset open in ViewTable - sas

Is there a way to replace a data set which is currently open in the ViewTable Window?
For example, say I create the following data set:
data the_meaning_of_life;
is = 2;
run;
I open it up and notice, oh drat!, I made a typo! I correct the code and rerun it.
data the_meaning_of_life;
is = 42;
run;
I'm then met with the following message,
ERROR: You cannot open WORK.THE_MEANING_OF_LIFE.DATA for output access with member-level
control because WORK.THE_MEANING_OF_LIFE.DATA is in use by you in resource environment
ViewTable Window.
Of course there are workarounds. In the keys menu, I could bind
next viewtable:libref.dataset;end;
to an F key or prefix the submit button with it so that all VTs are closed before code is submitted.
I recognize that there's an assumption I'm making. I'm assuming that because the ViewTable Window is called a "ViewTable" that it is indeed a view.
According to SAS, a view is
a definition of a virtual data set that is named and stored for later
use. A view contains no data; it merely describes or defines data that
is stored elsewhere.
A view should be independent of the data set. It seems like the ViewTable opened when a data set is double-clicked in the SAS Explorer is not a 'true' view. So maybe my question should be revised to,
How do I view a data set as a view?

You view a dataset as a view by creating a view and then opening it. But you have a misapprehension of what a view is; specifically, a view can lock a dataset, if it's set up to do so (in some DBMSs), while it's operating. (More on that later.)
SAS is locking the dataset, not because it has to, but because it is the right thing to do here given how it works. When dealing with the issue of "How do you handle a viewtable window when the underlying dataset is modified", you have three choices, right (maybe four)?
Disallow changes
Update the viewtable to reflect the changes
(maybe) Indicate to the user that it needs to be refreshed
Ignore the changes, let the user have out of date information
ViewTable is a concept that's quite old - and uses pretty old methods. As such, the second choice isn't really possible - it's not something running in a way that can update in real time. The third isn't really either: it again would require SAS knowing that the change happened and having the ability to update the ViewTable window, which it doesn't currently do. Right now, ViewTable just grabs the data and shows it to you, and then never checks back. And option 4 is bad because you now have the user being confused as to what "true" is, especially since ViewTable actually allows for direct editing of the data (this is never something I would do, but it is possible!).
Hence SAS goes with option 1: lock the table from any changes, so you know you have the current information.
Also, a side note; ViewTable is an AF application, it isn't actually a View. ViewTable means "view a table", not "make a view from a table".
As to how you can handle this: writing a view won't help, unfortunately. Note this:
data class;
set sashelp.class;
run;
data class_view/view=class_view;
set class;
run;
Run that, open the view, then rerun the first data step. Yep, you still have it locked! That's because opening the view actually tells SAS to lock the dataset(s) that the view uses, for the same reason as above.
What you can do though:
data class;
set sashelp.class;
run;
proc print data=class;
run;
You can run that all day and it won't have any issue, since the proc print is just a static "view" that doesn't lock anything.
You can also use ODS TAGSETS.TABLEEDITOR, which gives you something a little more useful perhaps.
You can definitely use the keys options to close your tables. Better perhaps is to use Enterprise Guide, which has a nice option that tells EG to close all open datasets before running anything.

Related

How to change the data in a column in SAS Data Integration?

I have an existing ETL solution built-in SAS Data Integration, where one of the columns in initially set to have all null values. I want to populate that column with actual data. The original column in that table was set to receive numeric values with specific format and in format. After I am changing the code (that is the easy part), I notice that the column doesn't accept character values (I did not get an error, I just noticed the column still having all NULL values).
Can anyone help ?
So you have a table that is defined in Data Integration studio (1) and created by running the job (2) a long time ago with a numeric column. Let us call that table THE_TABLE that field the_field and the job, The_Job, that loads data into THE_TABLE
You must be aware of the fundamental difference
defining a THE_TABLE in DI studio, which creates a description of the table in meta data
creating THE_TABLE by running The_Job, which creates a file in a folder with data
If The_Job really creates THE_TABLE from scratch each time (which is typical for ETL jobs), it is sufficient to do change THE_TABLE and The_Job in DI studio. Your edits will only change the meta data, but the next time you run The_job, THE_TABLE wil be created with the the right structure.
However, if The_Job updates THE_TABLE or appends to it, your edits will not change the structure of THE_TABLE and your job will not be fit for the structure of the file THE_TABLE like it still exists in the folder, so you must convert THE_TABLE before running The_Job.
This can be done with a simple program like
data THE_TABLE;
set THE_TABLE (drop=the_field); /* forget about the numeric field */
attrib the_field length=$200 format=$200.; /* and create the character field */
run;
The correct attrib statement might well be in the code generated for The_Job somewhere.
Mind that in a typical setup with a development, test and production environment, you will need that program once in each environment.

Oracle APEX - Reusable Pages?

We have some tables in our database that all have the same attributes but the table is named differently for each. I'm not sure of the Architect's original intent in creating them in this way, but this is what I have to work with.
My question for all the expert Oracle APEX developers: is there away to create a reusable page that I can pass the table name to and that table name would be used in the reporting region and DML processing of that page?
I've read up on templates and plugins and don't see a path forward with those options. Of course, I'm new to webdevelopment, so forgive my ignorance.
We are using version 18.2.
Thanks,
Brian
For reporting purposes, you could use a source which is a function that returns a query (i.e. a SELECT statement). Doing so, you'd dynamically decide which table to select from.
However, DML isn't that simple. Instead of default row processing, you should write your own process(es) so that you'd insert/update/delete rows in the right table. I've never done that, but I'd say that it is possible. Basically, you'd keep all logic in the database (for example, a package) and call those procedures from your Apex application.
You could have multiple regions on one page; one region per table. Then use dynamic actions to show/hide the regions and run the select query based on a table name selected by the user.
Select table name from a dropdown or list
Show the region that matches the table name (dynamic action)
Hide the any other regions that are visible (dynamic action)
Refresh the selected region so the data loads (dynamic action)
If that idea works let me know and I can provide a bit more guidance.
I never tried it with reports, but would it work to put all three reports in a single page, and set them via an Item to have Server-Side Conditions that decide what gets shown in the page? You'd likely need separate items with a determined value for the page to recognize and display.
I know I did that to set buttons such as Delete, Save and Create dynamically, rather than creating two or more separate pages for handling editing of certain information. In this case it regarded which buttons to shown based on a reports' primary key being sent to said "Edit" page. If the value was empty, it meant you wanted to create a new record (also because the create button/link sent no PK). If said PK was sent (via a edit button/link), then you'd have the page recognize it and hide the create button and rather show the edit button.

Copy Records in Oracle Apex

I need to copy selected row values and store as a new record.
I am using Oracle Apex 4.2 and Tabular Form.
I need to use checkbox to select the rows and button copy. When i select multiple rows followed by click copy button to copy all the selected row values as new rows and save.
Can anyone Help
Copying Records Through an APEX Tabular Form Input
The idea of cloning existing records from a single table through an Oracle APEX Tabular Form works without much interference with the default design that you can set up through the APEX wizard for page region content.
Build a table with an independent primary key.
Suggested to include two auxiliary columns: COPY_REQUEST and COPIED_FROM for running copy operations. Specific form elements will map to these columns on the tabular form that will be set up.
Build an Oracle stored procedure that can read which records need to be copied. This procedure will be invoked each time the SUBMIT button is pressed.
(optional) Consider including a suppression of step (3) in the event that there is nothing to process (i.e., no records marked for copying).
The Working Table for Receiving Input: COPY_ME
TIP: You will have an easier time if you use the standard TABLE creation wizard. Designate CUSTOMER_ID as the PRIMARY_KEY and have APEX create its standard auto-incrementing functionality on top. (sequence plus trigger set up.)
Here's the sample data I used... though it doesn't matter. You can put in your own values and be able to verify what happened easily.
The Heavy Lifting: The Stored Procedure for Cloning Records in COPY_ME
This procedure works with 1 or more records at a time with a special identifier in the COPY_REQUEST table. After the task is done, the procedure cleans up and resets the request value again.
create or replace procedure proc_copy_me_request is
c_request_code CONSTANT char(1):= 'Y';
cursor copy_cursor is
SELECT cme.CUSTOMER_ID, cme.CUSTOMER_NAME, cme.CITY, cme.COUNTRY,
cme.COPY_REQUEST
FROM copy_me cme
WHERE cme.COPY_REQUEST = c_request_code
FOR UPDATE OF cme.COPY_REQUEST;
BEGIN
FOR i in copy_cursor LOOP
INSERT INTO copy_me (customer_name, city, country, copied_from)
VALUES (i.customer_name, i.city, i.country, i.customer_id);
UPDATE copy_me
SET copy_request = null
WHERE CURRENT OF copy_cursor;
END LOOP;
COMMIT;
END proc_copy_me_request;
There is also a column that can be hidden. It tracks where the record was originally copied from.
Note that the cursor is using the FOR UPDATE OF and WHERE CURRENT OF notation. This is important because the procedure is changing the records that are referenced by it.
APEX Page Setup Instructions
Set up a standard FORM type page and choose the TABULAR FORM style. Follow the set up instructions, taking care to map the correct primary key, and also to the PK sequence object created with the table in the previous steps above.
This is what your page set up will look like after these steps are completed:
EDIT The COPY_REQUEST Form Value:
Under the column attributes section, change the Display As option to "simple checkbox"
Under the list of values section, put a single value under the LOV Definition: Y (case sensitive in either way... just be consistent)
EDIT The COPIED_FROM Form Value:
Under the column attributes section, change the Display As option to "Display as Text(Saves State)". This is just to prevent users from stepping on this read-only field. You could also suppress it if it isn't important to know.
CREATE a New Process: Execute Copy Procedure
This is the bottom of the same configuration page, there are very few things to change or add:
Demonstration: Screenshot of COPY_ME Tabular Form Page in Action
The first screenshot below is before the page is tidied up and the checkbox control is put into place.
Plug in some test data and give it at try. The Page Process created in the step above conditionally invokes the stored procedure that processes all copy requests made at the same time when the SUBMIT form button is selected.
COMMENTS: If you spend enough time tinkering around with the built-in wizards in Oracle APEX, there are opportunities to learn new design patterns and process flows compatible within the tool. Adapting your approach can reduce the amount of additional work and frustration.

In enterprise guide, how do you re open a previous data steps output to view it?

I'm using enterprise guide 4.3.
When you run a data step the resulting output opens in a spreadsheet like table.
Then when you run a proc tabulate or similar, the spreadsheet like view of the data disappears and the table comes up in SAS Report or HTML form etc.
You can then run further commands on that dataset that was created in the data step.
Q. How can you get that spreadsheet like view of the dataset back? (assuming it's possible)
I know you can run the data step again and it will display it but that seems really inefficient, especially if the data step had lots of computations involved. The data is obviously 'sitting there' given you can still interact with it (with proc tabulate etc). I was really surprised to see that it drops off from the process flow view.
Apologises if I've name things poorly above, I'm an R beginning to dabble in SAS.
If I understood you correctly you run some code and the result comes up. Then you run some other piece of code, from the same Code node and the initial result gets removed from the process flow.
You can always find your dataset in the Server List. You can enable it by clicking View -> Server List.
There is also a trick that you can do. When you run your code and the dataset node is created in the process flow, you can do a simple query on it. Just do Right click -> Filter and query and make it do something simple that won't take too long.
Now, when you run your next piece of code, this node will not be replaced (at least this is what happens in EG 4.1).
If you mean viewing the resulting data set from a DATA STEP, choose View/Process Flow and double click on the data set you want to view. Also, within your program, log, data or result view, there should be tabs across the top that allow you to bring up the other items of the process flow.

Tell SAS not to add newly generated tables on the Process Flow

I have a SAS code that creates a lot of intermediary tables for my calculations. Thing is, I don't really care about this tables after the job is done, I only care to the finals results.
But, everytime I run this code, SAS add all the generated tables do my process flow, turning it into a huge mess (I am talking here of 40+ intermediary tables).
Is there a way to tell SAS not to add some tables to the process flow? Or at least to tell it not to add any tables at all? I am using SAS Enterprise Guide 4.1
Thanks in advance
Under SAS 9.1.x and 9.2.x (for Windows), it's possible to suppress the display of datasets in SAS client environments by prefixing the dataset name with "_TO". So in your code and/or tasks, you could call all your intemediate datasets _TO<DataSetName>, and they won't clutter up your process flow. But they will still be there and can be referenced in code and tasks.
If you do this and you're using tasks, note that it might be tricky to work out how to use the output data from a task as the input for another, if you can't see the dataset to select it. If you have trouble with this, comment on this post and we can address that.
Note that this "_TO" prefix thing is an undocumented, "hidden" feature that is to be deprecated in 9.3 - see this blog for details.
If you set the option "Maximum Number of output data sets to add to the project" (under Results General) to zero, it will not add any datasets to the project, but they'll still be available to view from the Server -> Library view (they'll be added to the flow at the point you request them).
I know this question is a year and a half old now, but if you are working with intermediate tables that can be deleted after you get the final results, SAS EG has a built in macro you can use for deleting these tables:
%_eg_conditional_dropds([table1], [table2], ... ,[table-n]);