How to get list of all Check Constraints in database for all tables of specific schema together at once, in Sybase ASE - sybase-ase

I am using following query to get the list of all constraints of a single table in my database
sp_helpconstraint 'schema.tableName'
and then I am extracting the "Check Constraints" from the result set and using it. But as I have to run the above query every time for each table, therefore this makes my process slower. What I want is- a query in which I can get either the list of all constraints with their definition or only the List of Check Constraints for all tables of the database at once. As this will help to speed up my process in Sybase ASE

This gives the table name as well:
select
object_name(constid) as "Constraint name",
object_name(sysconstraints.id) as"Table name" ,
[TEXT]
from sysconstraints join syscomments on syscomments.id =sysconstraints.constid
order by [Table name]

Check the following
select object_name(tableid) as "table name",
object_name(constrid) as "constraint name",
col_name(tableid,sysconstraints.colid) as "column name",
text as "constraint text"
from sysconstraints,syscomments
where sysconstraints.status=128 and sysconstraints.constrid=syscomments.id
The sysconstraints specification at http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36274.1572/html/tables/X20320.htm explains the status=128 it means it is a check constraint

Related

Better way of getting values from table without looping 300 queries

I have a query and a loop written that lists all the rows from a mysql table ("records") formatted in a HTML table.
One of the fields is "subject_id" which is an integer. I also have a table named "subjects" which corresponds to the same "subject_id" in the records table. Only two fields are in the "subjects" table, is an auto-index ID integer and a varchar(1024) for the subject title.
The value that returns from the "records" table is an integer. I want to perform a lookup on the integer from the "records" table for each row to output the text equivalent from the "subject_id" field.
My first notion, the kindergarten way, would be to throw in another query within the loop, effectively increasing my number of queries from 300 to 600 to load the page (no pagination is needed).
What would be a better way of this "sub query" aside from adding 300 more queries?
Edit:
I'm pulling the data from the table using a while loop and echoing my variable $r_subject (from: $r_subject = mysql_result($result,$a,"subject");). The value returned from the initial records table is INT. I want to take the $r_subject and then check it against the SUBJECTS table to get the string name associated with that INT id.
It's hard to know exactly what you need without seeing code, but from what I gather, you have 2 tables, one has the ID, the other has the text, so you would want to use a join.
The second thing is, you'll want to look at whether or not you really need 300 queries in the first place. That's a lot of queries to run and you should only need to run that many queries when you're running a bulk insert/update or something of that nature; other than that, you most likely could reduce that number substantially.
select
A.*,
B.title
from
records A,
subjects B
where
B.subject_id = A.subject_id
That's a single query that will produce all of the data you need for your page.
select
subjects.SubjectTitle,
records.whateverFieldYouWant,
records.AnyOtherField
from
records
join subjects
on records.subject_id = subjects.subject_id
where
records.subject_id = TheOneSubjectYouWant
but can't confirm without actual structure of tables and some sample data displayed showing proper context of what you are expecting out

A better logging design or some SQL magic?

I'm knee deep in modifying some old logging code that i didn't write and wondering what you think of it. This is an event logger written in PHP with MySQL, that logs message like:
Sarah added a user, slick101
Mike deleted a user, slick101
Bob edited a service, Payment
Broken up like so:
Sarah [user_id] added a user [message], slick101 [reference_id, reference_table_name]
Into a table like this:
log
---
id
user_id
reference_id
reference_table_name
message
Please note that the "Bob" and "Payment" in the above example messages are Id's to other tables, not the actual names. A join is needed to get the names.
It looks like the "reference _ table _ name" is for finding the proper names in the correct table, since only the reference _ id is stored. This would probably be good if somehow i could join on a table name that stored in reference_table_name, like so:
select * from log l
join {{reference_table_name}} r on r.id = l.reference_id
I think I see where he was going with this table layout - how much better to have ids for statistics instead of a storing the entire message in a single column (which would require text parsing). Now I'm wondering..
Is there a better way or is it possible to do the make-believe join somehow?
Cheers
To get the join based on the modelling, you'd be looking at a two stage process:
Get the table name from LOG for a particular message
Use dynamic SQL by constructing the actual query as a string. IE:
"SELECT l.* FROM LOG l JOIN "+ tableName +" r ON r.id = l.reference_id"
There's not a lot of value to logged deletions because there's no record to join to in order to see what was deleted.
How much history does the application need?
Do you need to know who did what to a value months/years in the past? If records are required, they should be archived & removed from the table. If you don't need all the history, consider using the following audit columns on each table:
ENTRY_USERID, NOT NULL
ENTRY_TIMESTAMP, DATE, NOT NULL
UPDATE_USERID, NOT NULL
UPDATE_TIMESTAMP, DATE, NOT NULL
These columns allow you to know who created the record & when, and who last successfully updated it and when. I'd create audit tables on a case by case basis, it just depends on what functionality the user needs.

MS-Access show only items that meet multiple criteria

I am new to Access and I am looking for a solution that is beyond the ability of the others in my company and may be beyond what access can do.
I have the following fields.
Date: Last Name: First Name: Test1: Test2: Test3:
I am looking for the following to happen.
On any single date a user may test multiple times.
If the user passes all three tests do not show any records with fails or any duplicate passes.
If the user fails any of the three tests, but has multiple failed records only show one.
If the user has the statement "NotUsed" in any field, but a pass in any other keep a single record for that date.
Thank You,
First, you need a primary key column in order to be able to easily and unambiguously identify each record. In Access this is easily achievable with a Autonumber column. Also, in the table designer, click the key symbol for this column. This creates a primary key index. A primary key is a must for every table.
Let us call this column TestID and let's assume that the table is named tblTest.
The problem is that your condition refers to several records; however, SQL expects a WHERE clause that specifies the conditions for each single record. So let’s try to reformulate the conditions:
Keep the record with the most passes for each user.
Keep records with "NotUsed" in any test field.
The first condition can be achieved like this:
SELECT First(TestID)
FROM
(SELECT TestID, [Last Name], [First Name] FROM tblTest
ORDER BY IIf(Test1='pass',1,0) + IIf(Test2='pass',1,0) + IIf(Test3='pass',1,0) DESC)
GROUP BY [Last Name], [First Name]
This gives you the TestID for each user with the most passes. Now, this is not the final result yet, but you can use this query as a subquery in the final query
SELECT * FROM tblTest
WHERE
Test1='NotUsed' OR Test2='NotUsed' OR Test3='NotUsed' OR
TestID IN ( <place the first query here...> )
Is this what you had in mind?
Another thought is about normalization. Your table is not normalized. You are using your table like an Excel sheet. As your database grows you'll get more and more into trouble.
You have two kinds of non-normalization.
One relates to the fact that each user's first name and last name might occur in several records. If, in future, you want to add more columns, like user address and phone number, then you will have to repeat these entries for each user record. It will become increasingly difficult to keep this information synchronized over all the records. The way to go is to have at least two tables: a user table and a test table where the user table has a UserID as primary key and the test table has this UserID as foreign key. Now a user can have many test records but still always has only one unique user record.
The other one (non-normalization) occurs because you have 3 Test fields in a single record. This is less of a problem if your tests always have the same structure and always require 3 tests per date, but even here you have to fall back to the "NotUsed" entries. There are several ways to normalize this, because a database can have different degrees of normalization. The tree ways:
Only one test table with the fields: TestID (PK), UserID (FK), Date, Result, TestNumber.
A test day table with the fields: TestDayID (PK), UserID (FK), Date + a test result table with the fields: TestResultID (PK), TestDayID (FK), Result, TestNumber
Then you can combine the two previous with this addition: Instead of having a TestNumber field, introduce a lookup table containing information on test types with the fields: TestTypeID (PK), TestNo, Description and in the other tables replace the column TestNumber with a column TestTypeID (FK).
See: How to normalize a table using Access - Part 1 of 4 or look at many other articles on this subject.

How to convert data type from Text to Yes/No inside an append query in MS Access?

In MS Access, I'm trying to append data from one table (Table A) into another table (Table B). Table A has a column of type 'Short Text' with a single value 'Even' or empty/null. Table B has an equivalent column of type Yes/No. I've to insert data from Table A to Table B, while doing this conversion - if Table A's column has 'Even' set Table B's value to True, otherwise, set it to False.
I've tried a query like the following but it didn't work:
INSERT INTO TableB( BookName, ChapterName, PageNo, Even)
SELECT name, chapter, page, IIf(UCase([Even or Odd]) = 'EVEN', True,False)
FROM TableA;
The above query gives me following error:
Microsoft Access can't append all the records in the append query.
Microsoft Access set 0 field(s) to Null due to a type conversion failure, and it didn't add 117 record(s) to the table due to key violations....
How can I make access change the value while appending the data?
As your error screen says, the problem is not in converting data types, the error is due to key violation.
Try inserting without this yes/no field, and you'll ensure in this.
You may have relationships between tables so that it doesn't allow to insert certainn values.
For the sake of any future searches, Here is my final query which did work:
INSERT INTO TableB( BookName, ChapterName, PageNo, Even)
SELECT name, chapter, page, IIf(UCase([Even or Odd])="EVEN",-1,0) AS EvenOdd FROM TableA;
Things to check, if there are data type differences between source and destination tables. In my case, the page column in source table was number and in destination was Short Text.
Also, the Primary key, which isn't part of the query, was Number instead of AutoNumber, that was failing, and hence I was getting the error.

Why is my query not updateable?

I'm trying to build an updatable view in Access for a user. Basically, the underlying tables look like this:
Accounts
--------
accountId
accountName
accountHolder
TransactionStatements
------------
statementId
accountId
received
month
year
The user wants a Query (view) that looks like this:
StatementView
-------------
accountName
accountHolder
year
janReceived
febReceived
marReceived
etc...
The SQL to accomplish this is straightforward using a transpose, but the resulting view is not updatable.
I've also tried doing multiple joins explicitly to accomplish this:
PARAMETERS [Enter Year:] Long;
SELECT accountName, accountHolder, year,
FROM ((Accounts a
INNER JOIN TransactionStatements ts1 ON a.accountID = ts.accountID) 'AND month = 1 (This isn't allowed for some reason?)
INNER JOIN TransactionStatements ts2 ON a.accountID = ts.accountID) 'AND month = 2 (This isn't allowed for some reason?)
WHERE ts1.month = 1 AND ts2.month = 2 AND ts1.year = ([Enter Year:]) AND ts2.year = ([Enter Year:])
But once again the result becomes non-updatable as soon as I add the second INNER JOIN. I've looked at this MS help page, but it hasn't helped me figure out the right way to do this.
It suggests Forms as an alternative, but building a custom form in Access appears to be an even more arcane and convoluted process than writing views.
Any suggestions?
Take a look at this very thorough list of reasons why recordsets are and aren't updateable:
When Recordsets Are Always Updateable
A recordset is always updateable when:
It is based on a single table.
It is based on a query based on a single table.
It is based on a query based on tables with a one-to-one relationship.
When Recordsets Are Never Updateable
A recordset is never updateable when:
It is based on a Crosstab query.
It is based on a Union Query.
It is an Aggregate Query that calculates a sum, average, count or other type of total on the values in a field.
It is an Update Query that references a field in the Update To row from either a crosstab query, select query, or subquery that
contains totals or aggregate functions
Note: By using a domain aggregate function in the Update To row of an update query, you can reference fields from either a crosstab query, select query, or subquery that contains totals or aggregate functions.
It is based on a Query that includes a linked ODBC table with no unique index.
The database was opened as read-only or is located on a read-only drive.
It is a SQL pass-through query.
It is a query whose UniqueValues property is set to Yes. (That is, it is a query with a DISTINCT predicate.)
Cartesian Joins (that is, a query that includes more than one table or query, and the tables or queries aren't joined by a join
line in Design view.)
Query based on three or more tables in which there is a many-to-one-to-many relationship. Note: Though you can't update
the data in the query directly, you can update the data in a form
or data access page based on the query if the form's RecordsetType
property is set to Dynaset (Inconsistent Updates).
Calculated fields. Even if the query itself is updateable, if a column in a query is based on a formula, the field cannot be
updated. However, if the other fields in the formula are updated,
the calculated field will automatically update.
Recordsets Are Updateable Under Certain Conditions
Some queries, especially those involved in a Join, will not be updateable under some conditions, but will be under others. In other queries, even if the query itself is updateable, some of the fields will not be. The following are cases of query problems and their corresponding solutions.
Query based on a Join of tables with no Relationship.
•Problem: If a query is based on two or more tables that DO NOT have a relationship established (with Referential Integrity enabled), the query will be non-updateable.
•Solution: Create a Primary Key or Unique Index on ALL of the fields used in the Join on the "one-side" table. To be clear, this means ONE primary key or unique index based on all of the fields, not separate indexes on each field.
In a query based on a Join of tables with a one-to-many relationship (1:M), you might not be able to edit the data in one or more fields.
Join field from the "one" side
•Problem: If you have a 1:M relationship created between two tables, you cannot change the primary key field (used in the Join) of the table on the "one" side of the relationship.
•Solution: Enable cascading updates between the two tables.
New records, if the "many" side join field doesn't appear in the datasheet
•Problem: In a query based on a 1:M relationship, you can create a new record and fill in the fields that come from the "one" side table, but if the join field from the "many" side table is not visible in the query (that is, the foreign key), you cannot add data to the "many" side fields.
•Solution: Add the join field from the "many" side table (ie, foreign key) to your query to allow adding new records.
New records on the "one" side that are duplicates of other "one" side records.
•Problem: When adding a new record, if you try to type into the "one" side fields, you will be attempting to create a new record. Even if you use the same primary key values, it will give you an error.
•Solution: Add a value to the "many" side join field (foreign key) that matches the "one" side join field (primary key) of an already existing record. The "one" side values will simply appear.
Join field from the "many" side, after you've updated data on the "one" side
•Problem: If you are currently editing fields from the "one" side of the relationship, you cannot change the "many" side join field (foreign key).
•Solution: Save the record; then you'll be able to make changes to the "many" side join field.
New records, if entire unique key of ODBC table isn't output
•Problem: This is different than #5 under Never Updateable. In this case, the primary key of the linked ODBC table exists, but is not added to the query.
•Solution: Select all primary key fields of ODBC tables to allow inserts into them.
Query does not have Update Data permissions
•Problem: Query (or underlying table) for which Update Data permission isn't granted.
•Solution: To modify data, permissions must be assigned.
Query does not have Delete Data Permissions
•Problem: Query (or underlying table) for which Delete Data permission isn't granted
•Solution: To delete data, permissions must be assigned.
Conclusion
The causes of non-updateable recordsets are many and varied. Some have solutions and others don't. Hopefully, this list will help you know the difference.
The above is taken, word for word, from the following blog: This Recordset Is Not Updateable. Why?
I felt it was best to copy and fully attribute rather than try to paraphrase, so that all of the information was given.
The first things I suggest you look at might be that your tables have proper indexing and their relationships are set up properly. Those are usually the two things I gun for first, and they tend to solve most of my own "non-updateable query" issues.

Resources