views:

1572

answers:

4

I am looking for a query that will work on Sharepoint 2003 to show me all the documents created/touched by a given userID.

I have found tables with the documents (Docs) and tables for users (UserInfo, UserData) but the relationship between seems a bit odd - there are 99,000 records in our userdata table, and 12,000 records in userinfo - we have 400 users!

I suppose I was expecting a simple 1 to many relationship with a user table having 400 records and joining that to the documents table, but I see thats not the case.

Any help would be appreciated.

Edit: Thanks Bjorn, I have translated that query back to the Sharepoint 2003 structure:

select 
d.* from 
userinfo u join userdata d 
on u.tp_siteid = d.tp_siteid  
and 
u.tp_id = d.tp_author 
where
u.tp_login = 'userid' 
and
d.tp_iscurrent = 1

This gets me a list of siteid/listid/tp_id's I'll have to see if I can trace those back to a filename / path. All: any additional help is still appreciated!

+1  A: 

I've never looked at the database in SharePoint 2003, but in 2007 UserInfo is connected to Sites, which means that every user has a row in UserInfo for each site collection (or the equivalent 2003 concept). So to identify what a user does you need both the site id and the user's id within that site. In 2007, I would begin with something like this:

select d.* from userinfo u 
join alluserdata d on u.tp_siteid = d.tp_siteid 
and u.tp_id = d.tp_author 
where u.tp_login = '[username]'
and d.tp_iscurrentversion = 1

Update: As others write here, it is not recommended to go directly into the SharePoint database, but I would say use your head and be careful. Updates are an all-caps no-no, but selects depends on the context.

Bjørn Stærk
+1  A: 

If you are going to use that query in Sharepoint you should know that creating views on the content database or quering directly against the database seems to be a big No-No. A workaround could be some custom code that iterates through the object model and writes the results to your own database. This could either be timer based or based on an eventtrigger.

Kasper
+1  A: 

DO NOT QUERY THE SHAREPOINT DATABASE DIRECTLY!

I wonder if I made that clear enough? :)

You really need to look at the object model available in C#, you will need to get an SPSite instance for a SiteCollection, and then iterate over the SPList instances that belong to the SPSite and the SPWeb objects.

Once you have the SPList object, you will need to call GetListItems using a query that filters for the user you want.

That is the supported way of doing what you want.

You should never go to the database directly as SharePoint isn't designed for that at all and there is no guarantee (actually, there's a specific warning) that the structure of the database will be the same between versions and upgrades, and additionally when content is spread over several content databases in a farm there is no guarantee that a query that runs on one content database will do what you expect on another content database.

When you look at the object model for iteration, also note that you will need to dispose() the SPSite and SPWeb objects that you create.

Oh, and yes you may have 400 users, but I would bet that you have 30 sites. The information is repeated in the database per site... 30 x 400 = 12,000 entries in the database.

A: 

You really shouldn't be doing SELECTs with Locks either i.e. adding WITH (NOLOCK) to your queries. Some parts of the system are very timeout sensitive and if you start introducing locks that the system wasn't expecting you can see the system freak out.

But really, you should be doing this via the object model. Mess around with something like IronPython and experimentations with the OM are almost downright pleasant.

Mark Mascolino