Copy data from Table A to Table B, creating rows in the process, then delete data from Table A

I have a large table (~1000 rows) that I need to be archived to another table. Essentially, I want to have a sort of “closeout” feature where an admin user can click a button to kick off a workflow that automatically makes a backup copy of all the data from the Users table (I’m calling it Table A for this example) into an Archive table (Table B) then deletes the original data. This way, a record is kept of all the data for the users but they no longer will have access to the app because their account is no longer listed in the Users table. But I also have a group of users that I would NOT want to have removed from the Users table. To differentiate between the two groups, the ones I want to move have a UserID consisting of just numbers but the users I want to keep have a UserID that starts with the letter S (so some are “0000” and others are “S0000”).

It would be easiest to implement as a Workflow so that someone can use the app interface to accomplish this. A single button click that would move all the data over and delete the original data.

Ideas?

Sounds very doable with a manual workflow.

You don’t really have to send any data from a user-triggered workflow to do this, just use “Trigger Workflow” to allow your manual workflow to run.

Your manual workflow would loop through your Users table, find rows that match your condition, add them to the archived table, and then go back to delete the original row.

Though, I would just use a boolean column instead of the user ID method to deal with this.

I would suggest a completely different approach to this.

  • Create a separate table, lets call it Authorised Users. This table needs just a single column: Email address
  • Add a row to this table for every user that needs access to your App
  • Go to Settings->Access->Users, choose the “All emails in table” option, and select the Authorised Users table

The effect of the above will be that only emails that are listed in the Authorised Users table will have access to your App. Now when you need to remove a Users access, you simply need to delete their row from that table, without ever having to touch the Users table.

This is a much cleaner and simpler approach, in my view.

3 Likes

I agree with your thoughts here, it’s what I had thought of, too. But I don’t know what the triggered commands would be to go through this operation. If there’s 200 columns but I only want to carry over a specific 15 from Table A to Table B, how do I go through the operation?

1 - Create Row
2 - Copy Row from Table A, Columns 1 to 15 (note: they might not be concurrent in order)
3 - Paste Row into Table B, Columns 1 to 15
4 - Delete Row from Table A

In my specific case, I have ~1200 users and I want to archive the data for ~1000 of them when I trigger the workflow. Their data should be archived so that they no longer have access to the app, but I can still look up their information when I want to. And I want to be able to do this on a regular, annual basis.

For some background, I work with an educational camp (of sorts) that has around 1000 students and 100-200 staff. We want the staff to have year-round access to the app but the students only access it for the 1 week they are at the camp. After the camp finishes, I want to archive their data but NOT the staff data.

1 Like

In your loop you would have an Add Row action to add original row data to another table, followed by a Delete Row action to delete the original row. That really should be it.

But still consider Darren’s idea as well. A table with only user email and type would be used for access to the app. The user table would still contain user data, but not be used for app access.

Either way is valid depending on preference.

2 Likes

I would still recommend my approach, rather than messing around with workflows and moving data from one table to another. Consider the following:

  • if you are moving and then deleting 1000 rows with a workflow, then that will cost you a minimum of 2000 updates. My option will use zero updates.
  • if you have data in other tables that is related to data in the users table, those relations will break when you move the user record, along with any screens, etc that depend on them. My option does not have that problem.
1 Like

I thought about it more and I think your idea is in the direction that will work best, so thank you for that! I just want to discuss it a bit more and flesh it out. Here’s my thoughts:

Table A - the “Users” table that will be referenced by Glide to determine who has access
Table B - the “Archive” table that has all of the data for all of the users
Table C - the “Staff” table that has data for all of the staff

Table A will pull in referenced data from B and C, then Glide looks to Table A to allow people to sign in. Once the program is done for the year, I can delete all of Table A, keeping the Archive of data from B, then just re-insert all of the reference data from C back into A so that staff can maintain access.

So here’s the question: can I somehow make this process automatic or executable through a Glide app interface with a button/workflow? The initial creation of the Table B data (which is the students attending the program) can be done through either linking to an external Google Sheet to pull in the data or a manual copy/paste through the backend, but I’d like to eventually make this process be all accomplished through the app itself. For now, I’ll be happy to find a way to make a Workflow that says “Go through Table A, delete any data that is tied to an e-mail address already in Table B, but leave the values that are tied to an e-mail address in Table C.”

If it helps, each User row has a value identifying whether it is a member of Staff or is a Student. I might be able to just run an if-then boolean that identifies the Students for deletion only. But I’m still unsure of how to mass-import/reference all of the data from Tables B and C automatically into A besides having to copy/paste all of the e-mail addresses first, THEN introduce columns that lookup those e-mail addresses.

EDIT: Also, something to add: every user currently has a row in my Users table with a couple hundred columns. My app is built with a lot of functionality that writes to and references those columns. If I create a new “Authorized Users” table that pulls in the email addresses from there, would that break the functions in my app elsewhere?

What you summarized here is not what Darren and Jeff suggested.

From what I’ve understood:

  1. Table A. This is the Users table. It is referenced by Glide to create the user profile screen, to determine roles and it allows easy deletion of a user from inside Settings. Glide would not reference this table for access. This table would be the users archive in that it would store all of the data for all of the users.

  2. Table B. This is the Authorized Access table. It would be referenced by Glide only to determine who has authorized access to the app.

  3. There is no table C for staff. Staff users would all live in the Users table (table A) by default. The role of staff users could be set to “staff”. Staff users who have access to the app would appear in the Authorized Access table (table B).

First off, I know this is probably getting a bit confusing with the names of tables and such, so I appreciate everyone offering help!

After looking through the responses and thinking about it more, I think the easiest solution might be…simply adding a single Boolean column for “Has Access.” Checked means they have access, unchecked means they don’t. Then I would make a workflow that checks every row, looks for “student” as their role, and automatically checks it to “doesn’t have access” when I set it off.

This would solve the issue in the simplest way, right?

EDIT: I found some old discussions on the Community forums about how to set one specific value somewhere (such as “current session”) then have a column check for an if/then on that value and update accordingly. This is DEFINITELY the easiest way to do this. I can just set a sort of “give student access / remove student access” button to a boolean, have every row read that boolean, and…that’s it!

How would this boolean translate to having access or not (other than that being the title of the column)? In other words, how would this boolean tell Glide’s authentication that users X, Y and Z have access but users A, B, and C don’t?

Go have a look at >Settings >Access. This is where you control who has access to your app. Darren and Jeff’s recommendations are based off these settings.

What I’m thinking is that I can have all of my pages set to Visibility for people who have “Access” only, and the access is determined by a boolean.

With visibility conditions, technically speaking, everyone would then have access to your app. You would then display different screens.

By preventing access, I think other contributors understood that users would be prevented from signing in: no access at the sign-in level.

Another idea then more in line with your idea: you could set “access” and “no access” as roles, and then use row ownership in other tables. I find this complicated but it’s an approach.

Understand that visibility conditions don’t prevent the data from being downloaded (and therefore expected) to the devices of users, they only prevent that screen from displaying the data.

More on visibility conditions and why appearance ≠ security.

I agree, the idea of just trying to lock out “access” by changing visibility might not do quite what I want it to do.

My Users table has a bunch of columns that need to read other columns from other users to calculate some things, so Row Owners in the Users table wouldn’t work. And if I make a new Table with just email addresses into my new “Users” table, I don’t know if that would really fix this issue. I think my current app design kind of locks me out of this more secure option. Which is probably okay because the only personal information that is kept in the tables is the user’s email address. But I’ll still investigate a better setup on my end and see what I can come up with.

The problem that I’m trying to resolve is that my Users table will have around 1000 students and 100-200 staff, and I only want to delete the student e-mail addresses without deleting the rest of their data. If there are some students and staff kind of interspersed with each other, I need to find a way to filter the data out and only delete the student data. And my goal was to do this without having to go into the Data editor, instead being able to do this with a simple command within the user interface of the app. That’s why I thought having a single boolean switch to enable/disable all of the “Student” role accounts would be the easiest thing.

Ideas?

Clearly, you are not understanding my suggestion, and are overcomplicating this whole thing unneccessarily.

Do not touch or change anything in your Users table, or your User Profile settings.
The Authorised Users table that I suggested is not a new Users table, it is simply a table with a list of email addresses that Glide will reference to determine who can sign into your App. You control access to your App simply by adding or removing rows from that table. Thats it. No more, no less.

1 Like

I feel like Darren’s idea might solve your issue exactly and it happens to be simple to implement:

  1. Create a new “Authorise access” table.
  2. Add an email column to this table (and delete the default name column while you’re at it).
  3. Add all the email addresses that are to have access to your app.
  4. In >Settings >Access, change the app’s access setting and reference the “Authorise access” table. That’s it.
  5. Now, when a new user needs to be granted access to the app, add their email to the “Authorise access” table. When their access needs to be revoked, remove their email from the same table.
1 Like

@MJolley respectfully, please take the time to read, understand, implement and test the suggestions. You will see what has been suggested by the fellow experts IS the BEST approach.

3 Likes

I just want to reiterate that I really do appreciate the responses and suggestions. If it seems like I’m complicating things too much, there’s a reason for that.

I will set up an “Access List” table with the email credentials for all users, and a separate “Users” table with all of the actual data for the users. Once a user is supposed to have their access revoked, I will delete them from the “Access List” table. This allows me to keep their data in the Users table for archival purposes.

But I have 2 issues that still need to be resolved:

1 - how do I automate this process so that it can be done by a user of the app with the tap of a button? I’m thinking I can make my “Access List” table include a looked-up value from the “Users” table that is a Boolean for “has access / doesn’t have access” which I can set for all the users I choose (such as the “Student” accounts but not the “Staff” accounts), then run a workflow to delete the rows of the users who are set to “doesn’t have access.” But will this use updates to run?

2 - the next phase of my app is determining the security level for the data. The only piece of data that is private would be the e-mail address itself (all other information in the app is not sensitive PII for the users) but I don’t think some of the functions of my app will work, as it is currently designed, if I set my “Users” table to have row owners. However, this might be a good opportunity to set the “Access List” table to row owners when I implement it and then have any background calculations done in the “Users” table but pulled in to the “Access List” table.

Thoughts?

Thank you again for the help on this. It’s been excellent! Also, my app is over 90% complete because of the assistance I’ve received over the last year so the stuff I’m figuring out right now is mostly the fine-tuning around the edges of what is left.

Wouldn’t this still be a manual record by record process? Instead of setting a Boolean and pulling that into another table to then run a workflow, it seems like it would make more sense to just add or remove a row directly via a button on each student screen instead of a checking or unchecking a checkbox.

Maybe when adding a new student, you automatically add a row to the access table as well. When revoking access for a student, you remove the row from the access table. I don’t know…maybe I’m not understanding how the checkbox would help, unless it’s automatically being checked or unchecked by some other process.

Can you explain how the access checkbox would be checked or unchecked?

There is zero benefit to setting row owners on the access table. Especially since your user table would still contain email addresses.

Not sure I quite follow what your plan is, but if a user has access to a user row, they also have access to all data in that row whether they see it in the app or not. The only way to secure it is to restrict access to it, but like you said, it might break the functionality of the app. Can students view other students, or only staff can view students? If it’s only staff, then maybe Row Ownership with Roles is solution to consider. You could maybe utilize the hide emails option if the email address needs to be protected, but that’s not helpful if you are adding user rows yourself or need to know the actual email address.

Overall, I think some clarification regarding how user rows are added and how to would you set them as inactive would help. Like I said, if you are manually setting a checkbox, then you might as well skip that step and add or remove from the access table directly instead of making it a two step process. If the ultimate goal is just to remove access for all students in one shot, then a relation to the access table which grabs only student rows, and a delete action on the relation should suffice (no complex workflows or loops).

2 Likes

Yeah, let me outline the process in a bit more detail.

1 - all students and staff register for our program through an outside service, completely separate from the Glide app I’m creating. Once this is done, we export a list of names, email addresses, and what group they’re part of for the week-long camp. In total, there are around 1000 students and 150-200 staff members.

2 - the data from the other service is imported into the Glide app.in the “Users” table. This table has a couple hundred columns which will serve various functions throughout the week of the camp.

3 - during the week, students will be doing things like holding elections which are completely run through the app, exchanging fake money to each other, and “purchasing” items. All of this information is input and calculated through in-app interactions and captured by the many columns of each “Users” table row. Any important information for each student (such as any positions they were elected to) will be visible in their profile, in addition to a public profile system that will NOT share their e-mail address or any other PII. (This is the information that I want to retain after their access is revoked after the program.)

4 - at the conclusion of the program, all students will have their ability to log in revoked BUT all of their data should be kept as an archive. All staff members should maintain their ability to log in.

Ideally, since there’s only a few people who will have direct access to the Tables, I would like to come up with an in-app method for accomplishing all of these changes. For example, if there was a way to make an “upload student data” function where someone could import all of the data in step 1 through the app itself instead of through the Table backend, that would be great. And the same for revoking access at the end of the week.

Right now, I have a Table with a single row and each column is a various “status” for the camp, such as whether the camp has started, whether certain elections are open for voting, etc. One of those columns is “Allow Students to Access App” with a boolean. In the “Users” table, each user has one column stating “Staff” or “Student” and another that pulls in the value from “Allow Students to Access App” based on whether or not they are a “Staff” or a “Student.” This is how I use a single toggle switch in the app to state whether or not each specific user should have access. But I don’t have a good way to then turn that into a workflow and revoke access yet.

I’m thinking I can try making a workflow that loops through every “Access Table” entry, checks if the “Allow Access” boolean (which is pulled in from the “Users” table) is set to true or false, and then deletes the row if it’s false. But then I would also need a way to allow access in the first place, which is easy enough to do but uses thousands of updates in one command.