Showing ideas with label SAS_Access.
Show all ideas
SASware Ballot becomes SAS Product Suggestions
We have reformulated and renamed the communities-based board where you can enter your suggestions to improve SAS products. Read all about this change in the announcement -- and keep those great suggestions coming!
When using the XLSX option to read Excel data, I would like to be able to force an Excel column to be read into a character variable, even if the column contains only numeric values. With other engines, I believe this would be done with the DBSASTYPE option.
Sample code:
libname myfile xlsx "%sysfunc(pathname(work))\myexcel.xlsx" ;
*write sashelp.class to excel ;
data myfile.class ;
set sashelp.class ;
run ;
*Failing pseudo code to read in the Excel file, forcing Age to be character ;
data ClassCharAge ;
set myfile.class(dbsastype=(Age='CHAR(20)')) ;
run ;
Use case is that suppose I receive an incremental Excel file weekly, and I have a SAS job to load the data into a database. I have a variable that is defined as character in database, but some incremental Excel files may only have numeric values for that variable. When I import such an Excel file, it is loaded into a numeric variable in SAS even though the database and my SAS code expect it to be character.
Yes I can add code to by ETL job to check if the field is numeric or character and then convert it from numeric to character myself, and yes I hate Excel and could avoid this by converting the Excel file to CSV or just telling the customer not to send me Excel in the first place. But since many engines support the DBSASTYPE option, would be nice to see it supported by the XLSX engine.
Related thread:
https://communities.sas.com/t5/Base-SAS-Programming/Reading-XLSX-file-and-force-SAS-column-types/m-p/430934#M106536
... View more
See more ideas labeled with:
-
SAS_Access
Right now the below code produces CONTENTS output with no variable labels (or, the var names are repeated in the labels, which is about the same). That's a shame because Teradata has a nice field (and even table) commenting feature that seems to me the exact analogue of SAS' variable labels.
It should be possible to have these labels go into & come back out of the server's metadata tables.
libname td teradata &td_goo ;
data with_labels (label = "A nice descriptive label") ;
x = "Hey" ;
y = "Ho" ;
z = "Let's go!" ;
label
x = "The first word of the chorus"
y = "The second word of the chorus"
z = "The third word of the chorus"
;
run ;
data td.labels_gone ;
set with_labels ;
run ;
proc contents data = td.labels_gone ;
run ;
... View more
See more ideas labeled with:
-
SAS_Access
We all know that SAS develops its software in separate teams, but it can be really annoying when it becomes apparent that several associated teams haven't planned together how a SAS procedure will work.
I'm going to take as an example PROC IMPORT, which is part of Base SAS, but is also included in SAS/ACCESS. When you run the following program all the variables created begin with VAR, i.e. VAR1, VAR2, VAR3, VAR4, VAR5, etc., and this would also be true for DBMS=TAB and DLM:
PROC IMPORT FILE = "test.csv" DBMS = CSV REPLACE;
GETNAMES = NO;
RUN;
However, using similar PROC IMPORT code for DBMS=EXCEL, in SAS/ACCESS for PC Files, will create variables beginning with F, i.e. F1, F2, F3, F4, F5, etc.:
PROC IMPORT FILE = "test.xls" DBMS = EXCEL REPLACE;
GETNAMES = NO;
RUN;
More shocking though is using PROC IMPORT code for DBMS=XLS or XLSX in UNIX or Windows, in SAS/ACCESS for PC Files, as this will create variables with no prefix at all, i.e. A, B, C, D, E, etc.:
PROC IMPORT FILE = "test.xls" DBMS = XLS REPLACE;
GETNAMES = NO;
RUN;
This inconsistency even extends to using GETNAMES = YES too when there are multiple columns with the same label.
If you want to import a CSV file, instead of an Excel file, or indeed import an Excel file in UNIX, then the subsequent processing step will have to be updated to use the new variable names (annoying!). Why can't the procedure be consistent, or, at least, have a parameter, like PREFIX=, that allows users to choose the prefix?
... View more
See more ideas labeled with:
-
Base SAS Procedures
-
SAS_Access
Here is a log extract from SAS 9.4 (it has been the same for years): NOTE: Libref SCOUT was successfully assigned as follows: Engine: ODBC Physical Name: 7 libname scout clear; NOTE: Libref SCOUT has been deassigned. If you look in the Explorer of Display Manager you use File > New to connect a library and right-click Delete to disconnect it. If you look in the help for LIBNAME (9.4) you see: Associates or disassociates a SAS library with a libref (a shortcut name), ... So, we have assign/deassign, new/delete, associate/disassociate and clear. We also have LIBNAME and LIBREF. Does anyone else find this a confusing mess? What chance do SAS beginners have? New and Delete are completely wrong: the underlying files or data are not created or destroyed. Please could we have one pair of terms? I suggest connect and disconnect. That would be consistent with much database use.
... View more
See more ideas labeled with:
-
Base SAS Procedures
-
SAS_Access
Hi, Our datasets are currently stored in Google Big Query. Access from SAS is done via ODBC Connector (Simba ODBC Connector). This connector has to be improved by a specific connector, as it is done with Netezza, Oracle and many other DBMS. Indeed, for example, we can not manage to open Big Query dataset via SAS Enterprise Guide interface using click-button. There are other issues which impact the usage of SAS. Could you take my idea in consideration, il will be very helpful for our 80 users ? Regards, Gaetan
... View more
See more ideas labeled with:
-
SAS_Access
If I export a dataset with more than about one million records to Excel, it won't work because that is too much for Excel 2010 to handle.
Can proc export determine this before doing the export, rather than processing the export and after some time
breaking, with the error ERROR: Too many records for the output file?
This would save time if a dataset that is too large is exported, and save space - for the current process I'm building, I now see a dataset_name.$$1 file that's 120 MB.
Another suggestion is to make this a warning, or have an option to change this from an error to a warning.
... View more
See more ideas labeled with:
-
Base SAS Procedures
-
SAS_Access
tl;dr; For a case-sensitive database in SQL Server, the ODBC engine properly handles column names, but not table names. Note this is related to https://communities.sas.com/t5/SAS-Data-Management/Case-sensitivity-issue-with-ODBC-engine-and-SQL-Server-tables/td-p/349681 Let's say a SAS/Access engine is meant to access an external RBDMS table, Excel file, etc. as though it were a "virtual SAS dataset". Perhaps a sweeping, overly generalized statement, but let's go with it for now. Furthermore, let's say that consistency in how that engine works is a good thing. In this case, I’m referring to consistency in treating both table names and column names in a case-insensitive manner, in the same way that SAS treats SAS datasets. I'm working with SQL Server. I need to work with both case-insensitive tables (Latin1_General_CI_AI collation), and case-sensitive tables (Latin1_General_BIN collation). Some preliminaries/background: Latin1_General_CI_AI: Table names and column names are case-insensitive (in SQL Server itself) Filtering (WHERE clause) is case-insensitive, eg. WHERE current_record='Y' will return Y, y, and various accented y chars (if present in the data) (differs from SAS). Data is sorted (ORDER BY) in a case-insensitive manner (not in ASCII code order, and not matching SAS's default collation/sortseq) Latin1_General_BIN: Table names and column names are case-sensitive (in SQL Server itself). For the SAS programmer, this can be a "pain". Filtering (WHERE clause) is case-sensitive, eg. WHERE current_record='Y' will return Y only (like SAS). Data is sorted (ORDER BY) in a case-sensitive manner (in ASCII code order, and matching SAS's default collation/sortseq). Some test code: Create two databases in SQL Server, say CASE_INS and CASE_SEN. Configure the collation for CASE_INS as Latin1_General_CI_AI. Configure the collation for CASE_SEN as Latin1_General_BIN. Run this code in SQL Server Management Studio for both databases: USE CASE_INS -- then change to CASE_SEN and re-run
GO
DROP TABLE TeSt
CREATE TABLE TeSt (
FOO VARCHAR(3)
,Bar VARCHAR(5)
,BlAh VARCHAR(7)
)
INSERT INTO TeSt VALUES ('foo','BAR','Blah')
SELECT foo, bar, blah FROM test WHERE bar='bar'
SELECT FOO, Bar, BlAh FROM TeSt WHERE Bar='BAR' Note that both SELECT queries work for CASE_INS, but only the second query works in CASE_SEN. Now let's work with these tables in SAS: * 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 CASE_INS ODBC NOPROMPT="Driver={SQL Server Native Client 10.0};Server=MYSERVER;Database=CASE_INS;Trusted_Connection=yes;" schema=dbo;
libname CASE_SEN ODBC NOPROMPT="Driver={SQL Server Native Client 10.0};Server=MYSERVER;Database=CASE_SEN;Trusted_Connection=yes;" schema=dbo;
* case insensitive SQL Server database ;
* Note that all these scenarios work as expected ; * (with the possible exception of the case-insensitive where clause results) ;
data test1;
set case_ins.test (keep=foo bar blah);
where bar='bar';
by bar;
run;
data test2;
keep foo bar blah;
set case_ins.test;
where bar='bar';
by bar;
run;
data test3;
format foo bar blah;
set case_ins.test;
where bar='bar';
by bar;
run;
* case sensitive SQL Server database ;
* the below two scenarios fail ;
data test4;
set case_sen.test (keep=foo bar blah);
where bar='bar';
by bar;
run;
data test5;
set case_sen.TEST (keep=foo bar blah);
where bar='bar';
by bar;
run;
* this scenario correctly knows that the table exists, ;
* creates the column list in the correct case, ;
* but does not return the row. ;
* this is fine, since this is a case-sensitive table, ;
* and in fact is more in line with a where clause in SAS itself ;
data test6;
set case_sen.TeSt (keep=foo bar blah);
where bar='bar';
by bar;
run;
* this scenario works as expected ;
data test7;
set case_sen.TeSt (keep=foo bar blah);
where Bar='BAR';
by Bar;
run;
* this scenario fails due to the invalid column name ;
data test8;
set case_sen.TeSt (keep=foo bar blah baz);
where Bar='BAR';
by Bar;
run; In all of the above scenarios, we get these sastrace messages in the SAS log: ODBC: AUTOCOMMIT is NO for connection 3
ODBC: AUTOCOMMIT turned ON for connection id 3
ODBC_1: Prepared: on connection 3
SELECT * FROM "dbo"."test"
39 data test1;
40 set case_ins.test (keep=foo bar blah);
41 where bar='bar';
42 by bar;
43 run;
ODBC_2: Prepared: on connection 3
SELECT "FOO", "Bar", "BlAh" FROM "dbo"."test" WHERE ( "Bar" = 'bar' ) ORDER BY "Bar"
ODBC_3: Executed: on connection 3
Prepared statement ODBC_2 However, for the case-sensitive scenarios, we get these results: ODBC: AUTOCOMMIT is NO for connection 3
ODBC: AUTOCOMMIT turned ON for connection id 3
ODBC_10: Prepared: on connection 3
SELECT * FROM "dbo"."test"
ODBC: ROLLBACK performed on connection 3.
61 data test4;
62 set case_sen.test (keep=foo bar blah);
ERROR: File CASE_SEN.test.DATA does not exist.
63 where bar='bar';
64 by bar;
65 run; While I don't know the internals of the ODBC engine, this is my conjecture: 1) The ODBC engine is using SELECT * from "tablename" to determine if the table exists. 2) The query executes quite quickly, so it's only returning limited (zero?) rows, functionally equivalent to WHERE 0=1. 3) This query is within a TRANSACTION block (or the equivalent) and perhaps a TRY/CATCH block (or the equivalent). This conjecture is due to the ROLLBACK statement above. 4) If the query is unsuccessful, the decision is made that the table does not exist. 5) If the query is successful, the results are saved in a resultset. 6) The header of that resultset is compared to the SAS statements, in a case-insensitive manner, to generate the correct case-sensitive column list. Regardless of whether that conjecture is technically correct, IMO SELECT * from "tablename" is a poor way to determine if the table exists, since it relies on the table name being specified in the correct case. A better approach would be: SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE UPPER(TABLE_SCHEMA)='DBO' AND UPPER(TABLE_NAME)='TEST' or SELECT tbl.name AS TABLE_NAME FROM sys.tables tbl INNER JOIN sys.schemas sch ON UPPER(sch.name)='DBO' AND UPPER(tbl.name)='TEST' My recommendation: 1) Use either of the above approaches to determine if the table exists (and you have the required permissions). Check for the existence of the table in a case-insensitive manner. 2) If not, abort with table does not exist error. 3) If so, use the correct table name (including case) to load the resultset. 4) Use that resultset to build the correct column list (including case). IMO this behaviour would be more consistent with how SAS treats datasets and "virtual datasets" using case-insensitive names. Note: we are currently undergoing a SQL Server upgrade, and migrating from the default of collation of Latin1_General_CI_AI to Latin1_General_BIN, in order to match the default collation in SAS. The above behaviour of the ODBC engine will result in our need to refactor (or at least test) hundreds if not thousands of programs to ensure the table names are specified in the correct case.
... View more
See more ideas labeled with:
-
SAS_Access
Please provide support for the use of JDBC 'drivers' in SAS/Access. Providing support for the use of the "generic" JDBC API would provide indirect support for many databases, across many platforms. The cost of providing such support is low, since JDBC is already used for the Hadoop-specific interface. Having this support would allow us to use the JDBC drivers supplied by many database vendors to process their data in SAS; SAS could later, if they desired, provide vendor-specific interfaces as they have for DB2 for example, but the JDBC support would allow customers a way to access data prior to that happening. This also would be a boon to z/OS customers who sometimes have to use other middleware to access databases on distributed servers. One site I work at has successfully used the MSSQL JDBC driver from z/OS to read SQL Server data - but not in SAS.
... View more
See more ideas labeled with:
-
SAS_Access
Our organization is moving from Oracle DB Client (fat client) to Oracle Instant Client (thin client). So as a SAS admin I am forced to use the Instant Client instead of the actually used fat client. But my query to SAS Technical Support showed that the Instant Client is «not officially supported» by SAS Institute, cf. Technical Support Track # 7613206118. Strangely enough SAS mentions the Instant Client in its documentation Configuration Guide for SAS® 9.4 Foundation for UNIX Environments (in the section «SAS/ACCESS Interface to Oracle» on page 62 and 63). SAS Technical Support proposes us to continue with the fat client, which collides with the technology release plan of our organization. And moving to the Instant Client without the Support commitment by SAS could lead to support constraints by SAS. Therefore I request that SAS Institute works towards supporting the Instant Client.
... View more
See more ideas labeled with:
-
SAS_Access
SAS should include an IDENTITY column attribute to provide compatibility with other database systems. In my use case I would like to develop code that is 100% compatible between DB2 and SAS by simply modifying the LIBNAME statement. I can simulate IDENTITY column functionality by generating my own value, but that would not work for code that has already been developed for another database like DB2. I would need to know that I am in either a DB2 or SAS database environment and then have different code paths. Or eliminate the use of the DB2 IDENTITY column and always generate a number. Both choices are not feasible at the moment. Per Wikipedia: "An identity column is a column (also known as a field) in a database table that is made up of values generated by the database. This is much like an AutoNumber field in Microsoft Access or a sequence in Oracle. Because the concept is so important in database science, many RDBMS systems implement some type of generated key, although each has its own terminology"
... View more
See more ideas labeled with:
-
Base SAS Procedures
-
SAS_Access
We should be able to read and write Access using ODBC or some equivalent on Linux. There are other ODBC drivers available for Linux for other products.
... View more
See more ideas labeled with:
-
SAS_Access
0
Likes
When accessing help internet explorer is launched to access help online. SAS Support say "I can confirm that the behaviour you are seeing is expected and by design. Please note that the help of some of the procedures point to a specific User's Guide, such as the SAS/STAT User's Guide in the case of the GLIMMIX procedure, and these User's Guides are not part of the offline help files that are installed on your computer. Thus, it is not possible to prevent these from being redirected to the SAS Documentation website." There are many circumstances when working offline is essential or simply the only option due to lack of internet coverage. The change to online help from locally installed help is a regressive step which limits the functionality of SAS.
... View more
See more ideas labeled with:
Along the lines of having better control of messages in the log, provide a way to disable warnings when a Hadoop string is 32k in length.
If I run:
proc sql;
connect to hadoop ( &hadoop_connection.);
select * from connection to hadoop ( describe extended TABLE );
I get the message:
WARNING: The following columns could have a length in SAS of 32767. If so, SAS performance is impacted. See SAS/ACCESS documentation for details. The columns read from Hive followed by the maximum length observed were: col_name:450, data_type:639, comment:0
I should be able to query to Hadoop metadata without warnings.
... View more
See more ideas labeled with:
-
SAS_Access
Hello,
This may be a hard one to do but in line with the current direction it would be good to see support for Presto. Alot of other vendors have added it in the past year.
Link: https://prestodb.io/
... View more
See more ideas labeled with:
-
SAS_Access