Is USER_NAME column unique in HANA DB USERS table? - hana

Is USER_NAME field/column unique in HANA Database USERS table? I am seeing just number in USER_ID values.
Like BNAME in SAP USR02 table, I want to know what is the unique(or equivalent to bname) value field in HANA DB USERS table.

Amandeep Modgil's answer is not wrong but does not fully answer the question.
Of course, the documentation makes it clear that user names in SAP HANA need to be unique. However, it does not specifically explain whether or how this is enforced/guaranteed.
The "DB dev way" to find out something like this is to check the table structure used by HANA to store users.
Looking at the PUBLIC.USERS objects, we realize: this is not a table but a view instead.
Views don't have any constraints assigned to them, so any primary key or unique constraint must be implemented with one of the tables referenced by the view.
The next step is to review the source code for the view. In SAP HANA Studio one can simply mark the name of the view in the SQL editor and choose "Show Definition" from the context menu.
For PUBLIC.USERS this opens two(!) new windows:
one for the public synonym (there really is no PUBLIC schema, just synonyms) for USERS
and another one for the view SYS.USERS
This SYS schema is where SAP HANA system objects are implemented, so it's not surprising to find the view for USERS here.
In my HANA Express 2.00.045 system, the source code for the view surprisingly begins with
CREATE **ROW TABLE** "SYS"."USERS" ( "USER_NAME",
"USER_ID",
"USERGROUP_NAME" ...
That's weird at the very least, and I suspect it might be a bug as all other metadata entries for this object make it clear that this is in fact a view.
But I digress...
The question to answer was: where is the uniqueness of USER_NAME enforced?
Scrolling down the last main FROM-clause of the SYS.USERS-view points to a table: SYS.P_USERS_.
The trailing underscore in the name indicates that this is an internal HANA object that should never be directly used by any user or application. But that does not stop us from looking at it. Appropriate privileges are required for that, though. The "normal" application user account probably won't be able to directly look at this table's definition. I'm just using the SYSTEM user in this case.
Anyhow, we use the same technique as before: mark the SYS.P_USERS_ table in the SQL Editor, choose "Show definition" and we get: the definition of the table that holds the user accounts in SAP HANA.
The first three columns are defined like this:
Name SQL Data Type Dimension Column Store Data Type Key Not Null
OID BIGINT FIXED X
NAME NVARCHAR 256 STRING
LAST_SUCCESSFUL_CONNECT TIMESTAMP LONGDATE ...
Notice how there is no primary key defined on this table and how only OID has a NOT NULL constraint?
Clearly, the uniqueness of NAME is not guaranteed by table constraints.
So what else could it be?
Let's switch to the Indexes tab of the table definition and we find:
IDX_P_USERS_OID, indexed columns: "OID" ASC
IDX_P_USERS_NAME, index columns: "NAME" ASC
AND for both of these indexes the Unique-flag is set.
And there we have it:
Both OID (exposed as USER_ID) and NAME (exposed as USER_NAME) are unique in SAP HANA, enforced by unique indexes on the internal table that holds these user account entries.

You can look up the schema information on SAP portal link below:
https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.01/en-US/21026099751910148e0cdbddc75652b8.html
Although it does not tell you whether a particular column is the primary key or need to be unique, but you can combine this information with the data from following system view and get the information you are after.
https://help.sap.com/viewer/4fe29514fd584807ac9f2a04f6754767/2.0.05/en-US/210197377519101481cfb213f0b84848.html
I have highlighted the columns in the tables system view you need in the screenshot below

Related

Oracle APEX: Assign primary key as interactive grid ROWID, Use select Interactive Grid ROWID in SQL query

To preface -- I am as green as at gets.
I am tasked with building an app for internal org use. We have a DB with patient data, and in interface with a hospital electronic medical records system. patient data entered into the EMR is sent to us via interface to update the patient profile in our database. Partial matches require manual intervention.
Message is received in a table within a staging schema
attempts to match to existing patient
if there are only 'partial matches' a status is set to 'mismatch'
I want to:
Display a summary of all 'mismatch' status records. I want to use an interactive grid to select individual records.
Set ROWID of interactive grid rows to the respective primary key of the record in the staging table.
Use the selected Interactive Grid ROWID (user selects a specific record in the interactive grid) to select the matching primary key of the corresponding record in staging table to create SQL query to find potential matches within our DB. Potential matches are displayed in a second table.
Questions:
How do I set the rowID of an Interactive grid to the unique key column of the staging table?
--Some research shows I need a hidden item, is this correct?
How do I access a rowID that has been selected in the Interactive grid to use in a SQL query?
My humble thanks and appreciation
So, your question is a bit confusing, but as far as I understand it. You are getting some data from table A, trying to match it with table B. If it matches, it irrelevant for us. If a match is not found you want to show it so that it can be manually matched.
In apex in order to update a table, you need to select what is the primary key by which it will update the data. That is usually a column in the table, but it can also be rowid(just include it in the SQL like any other column).
What I would suggest for you from what I understand of your situation.
Display the mismatched rows in an interactive grid, with rowid as primary key. Then you will need to have a column by which you match, if these entries already have some sort of key by which you tried to match but failed, display that. And have that column be a PopupLOV so the user can edit what value is in that field and set it to the appropriate match. One thing you will need to be careful about. You are editing a Unique key, or perhaps even Primary key, you might get conflicts here. Even if you only display unmatched data in the LOV, you can still have a user editing multiple rows and trying to match two rows to the same value, that will fail with an error that isnt particularly user friendly.

How to query all Foreign keys in each table using SQL?

I have a database with more than 1600+ tables, and I need to know the foreign keys of each table. I only know how to look for foreign keys manually by clicking the table > column. How to query it and show it in one table along with the table name?
The SQL standard defines catalog tables and catalog views for this purpose in the schema INFORMATION_SCHEMA.
E.g. "The REFERENTIAL_CONSTRAINTS table has one row for each row in the TABLE_CONSTRAINTS table that has a CONSTRAINT_TYPE value of “FOREIGN KEY”." and "CONSTRAINT_COLUMN_USAGE view [...] Identify the columns used by referential constraints, unique constraints, check constraints, and assertions defined
in this catalog and owned by a given user or role.".
There are several tables/views to inspect for your particular purpose.
If your SQL engine supports INFORMATION_SCHEMA, look in the INFORMATION_SCHEMA section of your product's documentation.
If your SQL engine does not support INFORMATION_SCHEMA, then its catalog tables (if any) will be proprietary (and may possibly provide only rudimentary info) and you must inspect your product's doco for the detail of its catalog tables.

SQL Newbie: Use a foreign key for a lookup table being used like an enum() field?

Say I have field Ice_Cream.flavor, with the current choices in lookup table Flavor.flavor.
I use Flavor.flavor like an enum() list, storing the value, not the record ID, in Ice_Cream.flavor. If Flavor.flavor changes, I don't want to update Ice_Cream:flavor. I want it to stay as created.
Should I set up Ice_Cream.Flavor as a foreign key, so I can see the source of the values in my ER diagram, or not?
If you want Ice_Cream.flavor to stay as created even if there is no matching record in Flavor (which is what your question sounds like) then you cannot create a FOREIGN KEY relationship, it will not allow that condition to occur in your database.
Furthermore, if you're storing the actual text Flavor.Flavor string in Ice_Cream.Flavor, there's no particular reason to have a separate RecordID column in Flavor.
IMHO, you do not need a FK here except if you have additional informations about a flavor in the Flavor table beside the name in the column flavor. It is the case because you do not keep an ID, you keep the name AND you want to keep the old value.
I also supposed that you do not want to keep old flavors in the Flavor table or elsewhere except in the Ice_Cream table.
Last but not least, a FK would require that any flavor stored in Ice_Cream.flavor exists in the Flavor table. It is not the case if I understand correctly your question.

SQL database design suggestion : Naming a database table

I have to create a table and store Active Directory SIDs representing an User or a Group.
How would you name the category representing both an User and a Group ?
Edit 1.
Table will contain four columns : ID ( PK ), SID's Name, SID's value and another column for SID's Type ( 0 for User, 1 for Group ).
Please suggest the table name, not only the columns names.
Active Directory uses the term "principal" or "security principal" for both. That also includes computers.
Here's a grahpic image from the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 that shows the hierarchy.
(source: microsoft.com)
So I would probably call my table Principals and have the three columns you mentioned:
PrincipalName (string)
SID (string or binary)
PrincipalType (0 for User, 1 for Group)
From most verbose to least:
ActiveDirectorySecurityIdentifiers
ActiveDirectorySIDs
ADSIDs
Good practices dictate that table names be plural and that the names should represent and describe the contents of the tables. Depending on your level of comfort any one of the above should do just fine.
When I recently had to do this (linking a DB user table to the AD accounts) I simply named the column ADSID.
I found this made good sense for us since we were querying using DirectorySearcher and the name for that property in the LDAP database is objectSid, so our queries looked like:
deSearch.Filter = "(&(objectSid=" + ADSID + "))";
Although, as I cut an paste that code from my project, I do wonder if maybe objectSid would have been a good column name too?
As far as naming the table, I hope you are storing additional information beyond the AD details here? Otherwise, why are you duplicating the AD database?
If you are storing additional information, then you should name the table according to whatever domain/business object is modelled by the table.
As I said, I was storing the data for users, so my table was simply called [Users].
Finally - perhaps you would benefit from normalising this out into a [Groups] and a [Users] table?

Creating database tables with "either or" type fields

I have a database that tracks players through their attempts at a game. To accomplish this, I keep a table of users and store the attempts in a separate table. The schema for these tables is:
CREATE TABLE users (
id BIGINT PRIMARY KEY, -- the local unique ID for this user
name TEXT UNIQUE, -- a self-chosen username for the user
first_name TEXT, -- the user's first name
last_name TEXT, -- the user's last name
email TEXT, -- the user's email address
phone TEXT -- the user's phone number
);
CREATE TABLE trials (
timestamp TIMESTAMP PRIMARY KEY, -- the time the trial took place
userid BIGINT, -- the ID of the user who completed the trial
score NUMERIC, -- the score for the trial
level NUMERIC, -- the difficulty level the trial ran at
penalties NUMERIC -- the number of penalties accrued in the trial
);
Now I need to be able to store attempts that come from "transient" users. These attempts should not be linked back to an existing user. However, these transient users will still be able to enter a name that displays in the results. This name is not required to be unique in the table, since it does not represent a "real" user.
My first thought was to create a new field in the trials table called name. If userid is null, I would know it is a transient user, but I would still be able to show the name fields in the results. This approach doesn't quite smell right, and it seems like it will make my queries a bit more complicated. Additionally, it seems like I'm duplicating data in a sense.
Another thought was to replace userid with a useref text field that would be some kind of formatted string representing the user. For example, if the value were enclosed in curly braces, I would know it's an ID, i.e. {58199204}. If the value were not enclosed, I would treat it as a transient user. This more accurately represents what I'm trying to do conceptually (i.e. it's either an ID or a transient user string), but it would really complicate my queries.
I'm using SQLite for the backend... It lacks some of the extended features of SQL Server or MySQL.
Any thoughts on these or another approach to the problem?
Without more information about why a transient user can use but not exist in the system, I concur with your idea to:
Add a NAME column to the TRIALS table
Make the USER_ID column in the TRIALS table nullable/optional in order to indicate transient user status
If you could allow a transient user to exist in the system, I would recommend:
Creating a USER_TYPE_CODE table
Update the USERS table to include the USER_TYPE_CODE column (w/ foreign key reference to the USER_TYPE_CODE table)
You can either create a UserType field in the users table, and add "transient" users to the Users table, but this might increase the size of the Users table, or create a UserType field on the Trials table and create an additional TransientUsers table.
This will allow you to distinguish the difference of userid with the UserType field.
I'd like to point out that you really shouldn't use the formatted string approach. What happens if a user finds a bugged input port into your database and inputs "{8437101}" (or whatever user ID they want)?
SQLite lets you mix types in a field. I'd suggest you do as you were thinking, but without the braces. Disallow numeric names. If the userid is a number, which is exactly when it matches an id in the users table, it is a user id. If not it's the name of a transient user.